PDA

View Full Version : OOP vs Procedural Python


ltethe
12-14-2011, 12:12 AM
Ok, I've read the wiki, I've read a half dozen examples involving bicycles, pies, and abstractions, I still don't quite get the advantage of OPP over Proc coding. I'm a newb to be sure, but I've started throwing everything into Class definitions (with little understanding if I'm even doing them right) cause OOP is the way to go. I have no doubt about that, but what makes it better is eluding me.

Below are two simple code snippets of a shader declaration, one in Proc format, one in Class/Obj format. If someone could tell me what advantages I'm getting with the Class/Obj stuff using the example provided, I'd appreciate it, because at my level, it just looks like I added a bunch of extra lines of code with no tangible advantage.

Procedural Definition
#define rig material
def createMaterial(name, color, type):
cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=name+"SG")
cmds.shadingNode(type, asShader=True, name=name)
cmds.setAttr( name+".color", color[0], color[1], color[2], type='double3')
cmds.connectAttr(name+".outColor", name+"SG.surfaceShader", f=True)

createMaterial ('red_rig_mtl',(1,0,0),'lambert')

Class Definition
class imShader:
def __init__(self, name, color, type):
self.name = name
self.color = color
self.type = type

def create(self):
#check for existing shader
#if The Shader exists: Don't create the shader

cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=self.name+"SG")
cmds.shadingNode(self.type, asShader=True, name=self.name)
cmds.setAttr( self.name+".color", self.color[0], self.color[1], self.color[2], type='double3')
cmds.connectAttr(self.name+".outColor", self.name+"SG.surfaceShader", f=True)

###############################
#create Shader
rigShader = imShader('red_rig_mtl', (1,0,0), 'lambert')
rigShader.create()


Bonus! If you notice in the class definition, I've got a couple lines of pseudo code for an if statement to check if the shader exists in the scene and not create the shader if it exist already. However, I can't figure out how to query that, I pulled the query logic from windows, but obviously shaderNodes aren't query able, so I'm still hunting down how to implement this.

ltethe
12-14-2011, 02:31 AM
Hmm... I think I just figured out part of my question.

In a procedure, I run variables through it, and I get an output. If I call up the procedure again, and run different variables through it, I get a different output, the procedure only holds the data from the latest proc run through.


def createMaterial(name, color, type):

cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=name+"SG")
cmds.shadingNode(type, asShader=True, name=name)
cmds.setAttr( name+".color", color[0], color[1], color[2], type='double3')
cmds.connectAttr(name+".outColor", name+"SG.surfaceShader", f=True)

createMaterial ('red_rig_mtl',(1,0,0),'lambert')

So here I've got a red material.

If I run the proc again:

createMaterial ('white_rig_mtl',(1,1,1),'lambert')

I now have a white material. If I were to query, or grab the values of anything contained within the proc, they would all be pointed to the white material, I've lost the container for the red material.

However, if I used a class declaration for the red material, when the red material is spit out, I also get the variables name, color, and type associated with it.

If I later use the class declaration for the white material, I get a white material, and the variables name, color, and type associated with it. But the values with the red material haven't been lost either, they are "meta" data that is associated with the material.

My logic good so far, or am I out to lunch?

Now to tackle this shader query conditional...

ltethe
12-14-2011, 07:33 AM
import maya.cmds as cmds

###############################Shader Class


#define rig material
class imShader:
def __init__(self, name, color, type,):
self.name = name
self.color = color
self.type = type

def create(self):
#checking if shader exists
createShader = 1
allShaders = cmds.ls(self.name, mat=1)
for shadeCheck in allShaders():
if (shadeCheck == self.name):
createShader = 0

if (createShader == 1 ):

cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=self.name+"SG")
cmds.shadingNode(self.type, asShader=True, name=self.name)
cmds.setAttr( self.name+".color", self.color[0], self.color[1], self.color[2], type='double3')
cmds.connectAttr(self.name+".outColor", self.name+"SG.surfaceShader", f=True)


print "Shaderexists... Exsisting shader will be used."




#####################################
#create Shader
rigShader = imShader('red_rig_mtl', (1,0,0), 'lambert')
rigShader.create()


Well, this is what I got so far this evening insofar as trying to get a shader class to check for itself before it creates itself. It doesn't work...

:p

NaughtyNathan
12-14-2011, 11:27 AM
nobody needs OO programming, it's just a paradigm, it doesn't actually allow you to do anything that cannot be done with procedural programming, it's just a different way of managing your data, so it makes certain operations "easier", or at least more conceptually "natural".

Personally I hate the way some people programming in python use classes with absolutely no regard to why they are using them. If your script does not make use of the power of objects and classes (or at least would be shorter without them and still work identically) it's nothing more than another layer of obfuscation that adds nothing.

don't use classes just because you can.

:nathaN

ltethe
12-14-2011, 10:19 PM
SOLVED, easily my favorite part of this whole coding dealio, the euphoric rush when something finally works, no matter how simple the problem is.
import maya.cmds as cmds
#define rig material
class imShader:
def __init__(self, name, color, type,):
self.name = name
self.color = color
self.type = type

def create(self):
#checking if shader exists
shadExist = 0
allShaders = cmds.ls(mat=1)
for shadeCheck in allShaders:
if (shadeCheck == self.name):
shadExist = 1
print "Shaderexists... Exsisting shader will be used."


if (shadExist == 0):
cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=self.name+"SG")
cmds.shadingNode(self.type, asShader=True, name=self.name)
cmds.setAttr( self.name+".color", self.color[0], self.color[1], self.color[2], type='double3')
cmds.connectAttr(self.name+".outColor", self.name+"SG.surfaceShader", f=True)


########################################################
#create Shader
rigShaderRed = imShader('red_rig_mtl', (1,0,0), 'lambert')
rigShaderRed.create()

And insofar as OOP vs. Procs. The most succinct explanation I've gotten so far is that Objects/Classes are definitions for things. Procs are definitions for actions.

So use objects/classes to define a missile. Use procs to determine whether the missile hits anything.

ltethe
12-14-2011, 10:27 PM
def shaderCheck ():
shadExist = 0
allShaders = cmds.ls(mat=1)
for shadeCheck in allShaders:
if (shadeCheck == self.name):
shadExist = 1
print "Shaderexists... Exsisting shader will be used."

Hmm, upon reflection, this section looks ideal to turn into a proc. How do I reference things in the class from without?

In this case, self.name hasn't been declared yet since it's in the class.

CGTalk Moderation
12-14-2011, 10:27 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.