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).
Hello, I'm trying to get a Phong tag to work with my ObjectData plugin similar to the Phong tags assigned to primitive Polygon Objects such as Sphere & Cube.
Using the py-rounded_tube_r13.pyp as reference, I'm currently calling a function from ObjectData.GetVirtualObjects that sets the Phong with BaseObject.SetPhong. In my ObjectData I'm creating a Phong tag in my overridden NodeData.Init function. The Phong Tag is not having any effect unless I make the Object Editable. I've tried removing the SetPhong call, but it doesn't make a difference.
SetPhong
How can I get the Phong tag to have an effect on my ObjectData object?
Thank you!
Hi @blastframe I think you get the concept wrong, Generator doesn't have a "proper" Phong tag, or at least the Phong tag you apply to it has no real meaning since Phong is not a hierarchical tag(like Texture is), but it affects only the current object and a generator don't have any Polygon Information. With that's said this Phong tag on the generator is very useful because it let you expose parameter to the user in a meaningful manner, so the Generator can know for each Polygon Object it will generate, it can basically Retrieve a clone of this Phong and apply the same value. But the generator still has the liberty to not do it.
So the proper workflow is
So this gives us code like that:
import os import math import sys import c4d from c4d import utils PLUGIN_ID = 1234569 class PhongDemoObject(c4d.plugins.ObjectData): size = 100 def __init__(self, *args): super(PhongDemoObject, self).__init__(*args) self.SetOptimizeCache(True) def GetVirtualObjects(self, op, hierarchyhelp): ret = self.CreateMyObject(op) if ret is None: return None ret.SetName(op.GetName()) return ret def CreateMyObject(self, node): newObj = c4d.PolygonObject(8, 6) newObj.SetPoint(0, c4d.Vector(-self.size,-self.size,-self.size)) newObj.SetPoint(1, c4d.Vector(-self.size,self.size,-self.size)) newObj.SetPoint(2, c4d.Vector(self.size,-self.size,-self.size)) newObj.SetPoint(3, c4d.Vector(self.size,self.size,-self.size)) newObj.SetPoint(4, c4d.Vector(self.size,-self.size,self.size)) newObj.SetPoint(5, c4d.Vector(self.size,self.size,self.size)) newObj.SetPoint(6, c4d.Vector(-self.size,-self.size,self.size)) newObj.SetPoint(7, c4d.Vector(-self.size,self.size,self.size)) newObj.SetPolygon(0, c4d.CPolygon(3, 1, 7, 5)) newObj.SetPolygon(1, c4d.CPolygon(3, 5, 4, 2)) newObj.SetPolygon(2, c4d.CPolygon(4, 6, 0, 2)) newObj.SetPolygon(3, c4d.CPolygon(6, 7, 1, 0)) newObj.SetPolygon(4, c4d.CPolygon(0, 1, 3, 2)) newObj.SetPolygon(5, c4d.CPolygon(4, 5, 7, 6)) # If the generator already have a PhongTag, jsut clone it otherwise define it a 92° phong shading phongTag = node.GetTag(c4d.Tphong) if phongTag is not None: newTag = phongTag.GetClone(c4d.COPYFLAGS_NONE) newObj.InsertTag(newTag) # Add the cloned tag to the new Polygon Object present only in the cache else: newObj.SetPhong(True, True, c4d.utils.DegToRad(92.0)) newObj.Message(c4d.MSG_UPDATE) return newObj def Message(self, node, type, data): # On the creation of the Object, via the Menu create a Phong tag on the generator # c4d.BaseList2D(1234569) will not trigger it if type == c4d.MSG_MENUPREPARE: # Create a phong tag and set the default value to 92° (so we see the phong shading) node.SetPhong(True, True, c4d.utils.DegToRad(92.0)) return True if __name__ == "__main__": c4d.plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="phongdemoobject", g=PhongDemoObject, description="phongdemoobject", icon=None, info=c4d.OBJECT_GENERATOR )
Regarding your issue about AttributeError: 'function' object has no attribute 'im_func': As written in the doc of NodeData.Message you are supposed to return a bool. (I agree the code sample is a bit weird because it doesn't show the return statement, I will fix it)
AttributeError: 'function' object has no attribute 'im_func':
I've opened a BugReport since the error could be more explicit I will look at it but I guess this is a leftover of Python2.7 since im_func is removed in Python3.
im_func
If you have any questions, please let me know, Cheers, Maxime.
Hi,
could you show us an example for your code not working? On R23 SetPhong seems to work properly, when tested from a Python generator object.
import c4d def main(): """ """ node = c4d.BaseList2D(c4d.Osphere) if op[c4d.ID_USERDATA, 1]: node.SetPhong(True, True, 3.14159 * .125) return node
smooth_sphere.c4d
Cheers, zipit
hi @blastframe, usually the BaseObject::SetPhong() is not called in ObjectData::GetVirtualObjects() but rather in NodeData::Message() when the message intercepted is MSG_MENUPREPARE.
BaseObject::SetPhong()
ObjectData::GetVirtualObjects()
NodeData::Message()
MSG_MENUPREPARE
Something like
if type == c4d.MSG_MENUPREPARE: node.SetPhong(True, True, c4d.utils.DegToRad(40.0))
Cheers, R
Hi @r_gigante & @zipit, Thank you both for your replies. I am still experiencing the issue, unfortunately. I can set the Phong angle manually, but I want to set (or override) my object's Phong angle with a tag. As can be seen in this image, the Phong tag is at 91⁰.
It should look like this. (side note: when the object is made editable, it creates a Phong tag with the angle set with SetPhong and deletes the previous one):
@zipit My issue is not with setting the Phong. My issue is that I cannot surface the Phong tag to the user as is done with the Cinema 4D Primitives. Here is a code example that shows how the Phong tag I'm creating does not associate with the object's Phong tag until it is made editable.
import os import math import sys import c4d from c4d import utils PLUGIN_ID = 1234569 class PhongDemoObject(c4d.plugins.ObjectData): size = 100 def __init__(self, *args): super(PhongDemoObject, self).__init__(*args) self.SetOptimizeCache(True) def Init(self, op): tag = op.MakeTag(c4d.Tphong) tag[c4d.PHONGTAG_PHONG_ANGLELIMIT] = True tag[c4d.PHONGTAG_PHONG_ANGLE] = c4d.utils.DegToRad(91.0) tag[c4d.PHONGTAG_PHONG_USEEDGES] = False c4d.EventAdd() return True def GetVirtualObjects(self, op, hierarchyhelp): ret = self.CreateMyObject() if ret is None: return None ret.SetName(op.GetName()) return ret def CreateMyObject(self): node = c4d.PolygonObject(8, 6) node.SetPoint(0, c4d.Vector(-self.size,-self.size,-self.size)) node.SetPoint(1, c4d.Vector(-self.size,self.size,-self.size)) node.SetPoint(2, c4d.Vector(self.size,-self.size,-self.size)) node.SetPoint(3, c4d.Vector(self.size,self.size,-self.size)) node.SetPoint(4, c4d.Vector(self.size,-self.size,self.size)) node.SetPoint(5, c4d.Vector(self.size,self.size,self.size)) node.SetPoint(6, c4d.Vector(-self.size,-self.size,self.size)) node.SetPoint(7, c4d.Vector(-self.size,self.size,self.size)) node.SetPolygon(0, c4d.CPolygon(3,1,7,5)) node.SetPolygon(1, c4d.CPolygon(3,5,4,2)) node.SetPolygon(2, c4d.CPolygon(4,6,0,2)) node.SetPolygon(3, c4d.CPolygon(6,7,1,0)) node.SetPolygon(4, c4d.CPolygon(0,1,3,2)) node.SetPolygon(5, c4d.CPolygon(4,5,7,6)) node.SetPhong(True, True, c4d.utils.DegToRad(40.0)) node.Message(c4d.MSG_UPDATE) return node """ #this throws an error: #AttributeError: 'function' object has no attribute 'im_func' def Message(self, node, type, data): if type == c4d.MSG_MENUPREPARE: node.SetPhong(True, True, c4d.utils.DegToRad(40.0)) return True """ if __name__ == "__main__": c4d.plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="PhongDemoObject", g=PhongDemoObject, description="phongdemoobject", icon=None, info=c4d.OBJECT_GENERATOR )
I got some errors without including the res folder, so I've uploaded it if you wish to demo it on your machine: Phong Demo Object.zip
res
@r_gigante I am calling BaseObject::SetPhong() as it is done in the example: py-rounded_tube_r13.pyp. In that file, the method that sets the Node's points & then the Phong (GenerateLathe) is called from ObjectData::GetVirtualObjects().
Using the code below threw this error AttributeError: 'function' object has no attribute 'im_func':
AttributeError: 'function' object has no attribute 'im_func'
def Message(self, node, type, data): if type == c4d.MSG_MENUPREPARE: node.SetPhong(True, True, c4d.utils.DegToRad(40.0))
Am I doing this incorrectly?
Thanks again.
It's working! Thank you @zipit , @r_gigante , & @m_adam ! Have an excellent weekend.
A note for future readers One issue with my demo code is I wasn't passing the op from GetVirtualObjects to the CreateMyObject method. @m_adam created a new object (newObj) and only calls GetTag on the op (variable name: node).
op
GetVirtualObjects
CreateMyObject
GetTag
node
phongTag = node.GetTag(c4d.Tphong)