Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi Kent,
thanks for your feedback.
Actually merging C++ and Python categories was an outcome of our beta phase, where some were of the opinion too many categories would not be desirable. But there's another reason we did so: Our C++ and Python APIs are actually so similar, that many answers hold for both languages. And lastly, if it were just for the C++ and Python tags, we probably wouldn't even ask for the tags. It's rather tags about version or API in use, we are interested in most. Oh, and by the way, although I have to admit it was less frequent in the old forum, but instead of asking for tags we were asking to post into the right category. Which by the way still happens with just the four we have here. Oh, oh... Kent, can you please consider using tags? See About This Forum. Thanks! Just kidding.
But anyway, these are our reasons, maybe others have different ones and agree with yours. Then please, provide us with your arguments and opinions. It's not that we wouldn't care. We have taken notes of all feedback we received so far and will evaluate this hopefully during November. So, it's actually a good time to provide such feedback.
Maybe we can also address your aversion of "oversized" text. We'll look into providing themes. But we also need to see, what we can actually achieve and maintain in a certain amount of time. After all we think, support work is more important than induldging in web design. One thing I can say for sure, though. It's not your age. Because with my age increasing I definitely need larger and larger text...
Now, for the community aspect. I'm really sorry to hear this. I can only say, no, it was not our intention to kill the community in Plugin Café. Believe me, quite the opposite. I'd be really interested in more opinions and suggestions on this topic. Here's how I see it:
For example @mp5gosu told us, how much he likes working in this new forum. And we can see him actively discussing and contributing.
Please, everybody, come in, join this thread and provide us with your feedback. Tell us what you want and need. Kent mentioned some good points here. One especially worries me. Help us make this forum the place you want to be supported in. Help us to make this the place you want to discuss your plugin development related topics in.
Cheers, Andreas
Hi,
thanks for the additional information and setting the tags.
The BitmapButton needs to be added to the dialog via AddCustomGui(). For example like so:
# Prepare a red bitmap for the button. w = 50 h = 50 bmpRed = c4d.bitmaps.BaseBitmap() bmpRed.Init(w, h) for y in xrange(w): for x in xrange(h): bmpRed.SetPixel(x, y, 255, 0, 0) # BitmapButton configuration bcBitmapButton = c4d.BaseContainer() bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True # Add a BitmapButton to the dialog. # _bitmapButton is a member variable of the dialog class buttonId = 2000 _bitmapButton = self.AddCustomGui(buttonId, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER|c4d.BFV_CENTER, w, h, bcBitmapButton) if _bitmapButton is None: print "Handle this error!" # Assign the image to the button. # Note: Let it create an internal copy as the created bitmap will be free'd, when scope is left. _bitmapButton.SetImage(bmpRed, True)
Thanks to everybody in this thread for all your kind words.
@C4DS said in Good Bye and Thanks for the Fish:
As mentioned earlier, this place won't be the same without you.
You may overestimate my contribution. Silently watching from the side line, my feeling is, Riccardo, Sebastian, Maxime and Manuel, though being handicapped by a little loss of man power, not only managed to continue to do a great job in here, but even managed to further improve. Just let the dust of change settle a bit and they'll excel even more.
And with the recent unraveling of the plot, this "ending of your novel" has sure taken a new twist.
I'm not quite sure where you are heading and which plot recently unraveled. But please believe me, my departure was not so much related to Maxon and certainly not connected to any announcements on Maxon's strategy of the recent past. I left a group of friends behind, mostly for private and to a certain extent selfish reasons, which I won't discuss in public. Yet, please, try not to read between the lines and do not interpret my silence against Maxon or the SDK Team. I really enjoyed being part of the ride. Having had the chance to meet all of you in here was really great. It's just sometimes you need to stop eating, when it tastes best. I'm pretty sure Forest Gump also said some fitting words, I just can't remember...
no worries, we'll get you there.
One recommendation: When doing Python development, have the Cinema 4D Console window open (Menu Script -> Console...). There you will be presented with errors.
I think, your problem will be, that you try to access op, probably intending to change parameters of the active object. In Script Manager doc and op are global variables predefined for convenience. In a plugin, you have to get these yourself using GetActiveDocument() and GetActiveObject().
op
doc
Bye, Andreas
Dear fellow developers,
my seasonal greetings to the entire community.
But I'd also like to take the chance to say thanks to "our" SDK Team, who served us so well during the entire year. Patiently answering even my most stupid questions, as if they had nothing else to do (which of course they most likely have)...
So, please, everybody in this community join me in saying:
Thanks for supporting us so well, Riccardo, Sebastian, Maxime and Manuel!
Everybody hopefully gets some well deserved days of rest.
Hi Andre,
you can simply use SetLink(), the opposite of GetLink().
SetLink()
GetLink()
In order to clear a link box, you'd call: self.linkBox.SetLink(None)
self.linkBox.SetLink(None)
The type you do in your code snippet is a bit unconventional in terms of Cinema 4D's API (not wrong though), but usually we recommend to stay in our API for example with CheckType() or IsInstanceOf(). But in the end, I think, you don't even need the type check, if you simply restrict the types accepted by the link box. For example like so:
CheckType()
IsInstanceOf()
bcAcceptedObjects = c4d.BaseContainer() bcAcceptedObjects.InsData(c4d.TakeBase, "") # only allow BaseTakes to be accepted bcLinkBox = c4d.BaseContainer() bcLinkBox.SetData(c4d.DESC_ACCEPT, bcAcceptedObjects) self.linkBox = self.AddCustomGui(2001, c4d.CUSTOMGUI_LINKBOX, "My Link", c4d.BFH_SCALEFIT | c4d.BFV_CENTER, 0, 0, bcLinkBox)
I turned this thread into a question.
no your script is not wrong. There's just a bit more to it.
NodeData
BaseContainer
GetParameter()
tool.GetParameter(2108, c4d.DESCFLAGS_GET_0)
you can also use the Description.
Description
With a small loop, you can get information about a tool's parameters and their type:
toolID = doc.GetAction() tool = c4d.plugins.FindPlugin(toolID, c4d.PLUGINTYPE_TOOL) desc = tool.GetDescription(c4d.DESCFLAGS_DESC_0) for bc, paramid, groupid in desc: # Iterate over the parameters of the description print bc[c4d.DESC_NAME], paramid[0].dtype # Print the current parameter name and type
It sounds a bit, as if you try to create some kind of undo system for tools. Something Cinema 4D does not have currently. The standard undo system for example works by cloning instances, something that is not possible with tools. But of course the cloning automatically takes care of the entire instance's state, regardless, if parameters are stored in the BaseContainer or if the complete state is really defined by parameters. So, just be aware, even with the above approach, there might still be information stored inside of a tool, which may not be reflected by the Description, either. I have no examples for this, it is more a word of a warning, something like this might come up.
no, you are not! Really there are no stupid questions and please do not delete such posts. Especially not, if you already invested time in posting the correct answer. We'd rather see this as knowledge others might benefit from in the future.
Sorry for joining in so late. And I think, all relevant points have already brought up. I just wanted to add one twist or slightly different point of view:
c4dpy is a so to say "standalone python interpreter" with access to Cineama 4D's api.
Actually c4dpy is a full headless Cinema 4D, which can be used as a Python interpreter in IDEs.
I know the subject sounds strange. Unfortunately I have not yet found the time to extract it into a small and clean example code. I am a bit under pressure with my timeline and already lost the entire day, trying to find cause and workaround for the issue.
I am only posting here, because I hope, it rings a bell with somebody and I get a "Duh, you dipshit, is this the first dialog you are writing? Of course you need to do it like so".
So, here's the issue. In a customer's plugin I have a quite complex asynchronous dialog (opened from a CommandData, pretty standard in this way). Quite a lot relies on InitValues() properly being called.
Usually we get a sequence like this:
Now, if the dialog is docked into the startup layout, the sequence changes slightly:
My problems start, if the dialog is docked into the layout and folded (e.g. by middle clicking it's title bar). Now, if C4D starts up, it looks like so:
So, I thought, I would need to come up with my own InitValues() call.
By now I have tried the following things:
a) I tried to send a CoreMessage from RestoreLayout(), right before exiting the function. This CoreMessage is never received. b) EVMSG_CHANGE is also no option. It doesn't happen upon unfolding the dialog. Neither is it received before. c) As i received no CoreMessage during this phase, I thought I'd pick an arbitrary message, which happens after CreateLayout() has been called and do a one time call to InitValues() there (basically with a flag, which is set in RestoreLayout and then reset after message got received). By this approach all hell break loose. Obviously CreateLayout runs in parallel to the thread calling my Message(), so i ended up with InitValues() being called, while CreateLayout was still running. The splatter in a Dario Argento moving is nothing compared to the results I received this way. d) This is what I currently use as a workaround, but I deem it a pretty ugly solution. Basically a small state machine. In RestoreLayout a flag is set, saying "coming from restore". At the very end of CreateLayout() in case we are "coming from restore" a flag is set "done with CreateLayout". With the next message (I arbitrarily picked one, which is coming reliably, didn't even check, which it is (id is 1651078253) I check, if I'm coming from restore and create layout is done and then initiate a call to InitValues(). This seems to work for the moment, but of course seems also like a pretty risky and "racy" approach. The "raciness" could be healed by emitting a CoreMessage in this case and then call InitValues when it is received. I dig this. But the entire approach feels so awkward to me...
I must have missed something really fundamental here. Something crucial to properly handle this situation.
Unfortunately searching the forum and browsing the SDK docs, I was not able to find any hints into the direction of my issue.
So, to wrap it up and try to summarize the question in a nutshell: What is the correct way to get a call to InitValues() after C4D has started up for a dialog that got docked and folded in the startup layout?
Any pointers would be very welcome! Thanks for your efforts in advance, I really hope the question is as stupid, as I fell right now.
Edit: Forgot to set tags... oh, unfortunately I can't set more than seven tags. I'm testing here on Win10. It is a Python plugin. And I have this issue in all versions of C4D I tested, meaning all from R17 up to S24.
Hi, has this been addressed in R23 SP1 release? Cheers, Andreas
I somehow doubt this is an issue that could be solved by changed priority. The Python tag is executed once during the execution of the scene (lets leave exceptions to this rule aside for now). Regardless of priority or exact execution order, the tag's code gets executed once. With priority you can change the point of time of this one execution or change the order of the execution of all entities contained in a scene. But in your Python tag you do modify the scene by changing the two links. And then you want to have the result of this change a few lines later. But nothing has changed so far. You have only changed a link parameter of two instances in the middle of C4D evaluating the scene entity by entity. In order for the Loft to change it's size, the Loft needs to be executed. But when you read the size, it's still the Python tag being executed... you get where I am heading? I don't think, what you are trying to do here is possible with a single Python tag. Instead do it in two. Have one assigning the links. The other places the cube based on Loft size. Then you can use the priorities of the tags to make sure, the execution order is as follows:
Cheers
Good catch, I fixed the post.
No, you didn't upset me. And I may have been a bit short, asking for actual errors. For me the latter indeed is an important point. You will help yourself a lot, improving the information contained in a question. For example when talking about errors, but not providing any information or details about the actual errors. On your journey into C4D development and Python programming the Console is your friend and more often than not it already contains good information to solve an issue (and even if messages therein seem to make no sense, they may mean something to others). If I have been too harsh, I apologize, but also please try to view it from the other side. The people wanting to help, spend time for this. Having to ask the same questions again and again, just to find out what the actual question or problem is, is just time lost. For the one wanting to help simply lost and for the one asking it only takes longer to get the desired answer. On top assume, there may be multiple people wanting to help, so parts of this equation even multiply... so asking good questions, will help you reaching a solution in shorter amount of time and save time on side of those helping, which in turn will increase chances to get help at all.
I hope, you don't get me wrong. Really in this case it wasn't a big deal and it was probably my fault, to just insist on an error message without further words. Sorry for that. And the above, while addressing you, you should actually rather read as a hint to everybody asking questions on any forum. In a nutshell, if you are having a problem, try to help other people help you.
And please keep asking questions. It's the best way to improve as a developer. Believe me, I know, what I am talking about. Looking at my code should be evidence enough, I asked way too few questions...
@mogh It looks as if my reply this morning somehow got lost. I basically asked, what errors you get exactly?
??? So, what are the errors? I have none...
I only briefly scanned this topic, but I have a few thoughts and questions. Simply ignore me, if I talk rubbish as usual...
Does this problem occur with every shader that supports subshaders or only a few? Does it happen with the layer shader as well, for example? If I remember correctly BaseLinks work only correctly (especially in AliasTrans context), if the linked object is a valid member of a document (e.g. in a NodeData for example via branch. Now, if my mind doesn't trick me, there are certain shaders, which do not properly hold there subshaders in the shader tree. Which caused me all kinds of issues, when trying to initiate shader updates from a NodeData and I ended up with special code for certain shaders (I think, it were mainly those stemming from good ol' Smells Like Almonds shaders), basically extracting the subshaders from their parameters.
And another thought, maybe you already tried and I overlooked it in this thread: Does using ForceGetLink() change anything for you, when trying to resolve those links? If I'm not mistaken, C4D also resolves links beyond a document's context with this.
how would I implement your code in python 3.x (R23)
Not sure, what exactly your problem is. I'm currently using a simpler version of above code in C4D R23 and it works for me. Well, I build the string a bit differently and the print is also written differently in Python 3. But this doesn't seem to be your problem. I'm aware there are parts of time module deprecated in Python 3, but... I mean, deprecated doesn't mean it's gone, only that it will be gone some time in future. And as I use it as a debugging tool, I don't care too much for the moment. The code is not meant to stay in my projects.
Can you post an error message maybe? I'm too lazy to test that exact version now.
I have been following this topic in all three (!) forums since beginning and I'm really looking forward to the outcome of this topic.
I'd call myself quite a Matrix mutant, so just ignore me, if my question is completely off topic or bogus in this context. My expectation would have been the same as @Cairyn's. Yet, there has always been this last sentence on the Matrix fundamentals page, which reads pretty suspicious to me.
[Local Matrix] = MatrixMove(op.GetFrozenPos()) * HPBToMatrix(op.GetFrozenRot()) * MatrixMove(op.GetRelPos()) * HPBToMatrix(op.GetRelRot()) * MatrixScale(op.GetFrozenScale) * MatrixScale(op.GetRelScale()) Please note that the both scales are applied at the very beginning, so the local matrix is not the same as [Frozen Matrix] * [Relative Matrix]. This is necessary in order to guarantee that your local matrix always stays a rectangular system; distorted sy
[Local Matrix] = MatrixMove(op.GetFrozenPos()) * HPBToMatrix(op.GetFrozenRot()) * MatrixMove(op.GetRelPos()) * HPBToMatrix(op.GetRelRot()) * MatrixScale(op.GetFrozenScale) * MatrixScale(op.GetRelScale())
Please note that the both scales are applied at the very beginning, so the local matrix is not the same as [Frozen Matrix] * [Relative Matrix]. This is necessary in order to guarantee that your local matrix always stays a rectangular system; distorted sy
I'm not questioning the correctness of this sentence. I'm just wondering if it may be related to this issue? And if one would maybe need to separate the scale from the equation and calculate it in correct order?
@zipit You are right. Forget my comment. I shouldn't have posted before my first coffee. Indeed I was triggered by the dialog not being closed, but then brain activity obviously went back to power save...