Phong Tag with ObjectData
-
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.How can I get the Phong tag to have an effect on my ObjectData object?
Thank you!
-
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
Cheers,
zipit -
hi @blastframe, usually the
BaseObject::SetPhong()
is not called inObjectData::GetVirtualObjects()
but rather inNodeData::Message()
when the message intercepted isMSG_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@r_gigante
I am callingBaseObject::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 fromObjectData::GetVirtualObjects()
.Using the code below threw this 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))
Am I doing this incorrectly?
Thanks again.
-
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
- Create a Tag in the MSG_MENUPREPARE so you expose to the user a UI to control the Phong shading.
- Attach a Clone of this Tag to all PolygonObject you generate within your Generator.
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)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.If you have any questions, please let me know,
Cheers,
Maxime. -
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 theop
fromGetVirtualObjects
to theCreateMyObject
method. @m_adam created a new object (newObj) and only callsGetTag
on theop
(variable name:node
).phongTag = node.GetTag(c4d.Tphong)