"""
    Copyright (C) <2010>  Autin L. TSRI

    This file git_upy/cinema4d/r12/c4dHelper.py is part of upy.

    upy is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    upy is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with upy.  If not, see <http://www.gnu.org/licenses/gpl-3.0.html>.
"""
# -*- coding: utf-8 -*-
"""
Created on Sun Dec  5 23:30:44 2010

"""
# C4d module
import c4d
from c4d.utils.noise import C4DNoise
# standardmodule
import sys
import os
import struct
import string
import types
import math
from math import *
from types import StringType, ListType

# usenumpy = False
# try :
#    import numpy
#    usenumpy = True
# except :
#    usenumpy = False
#    print("no numpy")

# base helper class
from upy import hostHelper
from upy.hostHelper import Helper

if hostHelper.usenumpy:
    import numpy

from c4d.threading import C4DThread


class UserThread(C4DThread):
    def Main(self, func, *args, **kw):
        # Put in your code here
        # which you want to run
        # in another thread
        if self.TestBreak():
            print "Canceled thread-execution."
            return
        func(*args, **kw)

    def cb(self, ):
        if self.TestBreak():
            return False
        return True

    def TestDBreak(self):
        bc = c4d.BaseContainer()
        c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.KEY_ESC, bc)
        # how to proceed?
        # break the process ?


class c4dSynchro:
    # period problem
    def __init__(self, helper=None, use_generator=False):
        self.callback = None
        self.object = None
        self.parentObj = self
        self.liste_cb = []
        #        if cb is not None :
        #            self.doit = cb
        #            self.parentObj = cb.__self__
        self.helper = helper
        if self.helper == None:
            self.helper = c4dHelper()
        self.use_generator = use_generator
        self.attrAcces = c4d.OPYTHON_CODE
        if not self.use_generator:
            self.attrAcces = c4d.TPYTHON_CODE
            # use tag or pythonGenerator?
            # can we access the text of the generator?

        #    def change_period(self,newP):
        #        self.period = newP
        #        self.remove_callback()
        #        self.set_callback()

    def add_callback(self, cb):
        self.liste_cb.append(cb)

    def set_callback(self):
        # create an empty
        self.object = self.helper.getObject("synchro")
        if self.object is None:
            if self.use_generator:
                self.object = c4d.BaseObject(1023866)  # python generator ?
                self.objectcb = self.object
            else:
                self.object = c4d.BaseObject(c4d.Onull)  # python generator ?
                pytag = self.object.MakeTag(1022749)
                self.objectcb = pytag
                # add the tag
            self.object.SetName("synchro")
            self.helper.AddObject(self.object)
        self.objectcb[self.attrAcces] = self.callback
        # need to change this to doit ...and pass the object

    def remove_callback(self, cb):
        i = self.liste_cb.index(cb)
        self.liste_cb.pop(i)
        if not len(self.liste_cb):
            self.helper.deleteObject(self.object)

    def create_str_for_cb(self, ):
        c4d.helper = self.helper
        c4d.synchro = self.parentObj
        c4d.synchro_cb = self.liste_cb
        self.callback = """
import c4d
theObj = c4d.synchro
theCallback = c4d.synchro_cb
helper = c4d.helper
def main():
    helper.doc = doc
    t=c4d.BaseTime()
    fps = doc.GetFps()
    #getCurrent time
    frame=doc.GetTime().GetFrame(fps)
    for cb in theCallback:
        cb(frame)
"""

    def doit(self, *args, **kw):  # period,time,userData=None):
        pass


class c4dHelper(Helper):
    """
    The cinema4d helper abstract class
    ============================
        This is the cinema4d helper Object. The helper
        give access to the basic function need for create and edit a host 3d object and scene.
    """
    # this id can probably found in c4d.symbols
    # TAG ID
    import c4d
    POSEMIXER = 100001736
    POSEMORPH = 1024237
    IK = 1019561
    PYTAG = 1022749
    Follow_PATH = 5699
    LOOKATCAM = 1001001
    SUNTAG = 5678
    DYNAMIC = 180000102
    CONTRAINT = 1019364  # Tcaconstraint

    # OBJECT ID
    BONE = 1019362
    CYLINDER = 5170
    CUBE = c4d.Ocube
    CONE = c4d.Ocone
    CIRCLE = 5181
    RECTANGLE = 5186
    FOURSIDE = 5180
    LOFTNURBS = 5107
    EXTRUDER = 5116
    SWEEPNURBS = 5118
    TEXT = 5178
    CLONER = 1018544
    MOINSTANCE = 1018957
    ATOMARRAY = 1001002
    METABALLS = 5125
    LIGHT = 5102
    CAMERA = 5103
    SPRING = 180000010
    PATHDEFORM = 1019221
    PLATONIC = c4d.Oplatonic
    POLYGON = c4d.Opolygon
    MESH = c4d.Opolygon
    SPLINE = c4d.Ospline
    INSTANCE = c4d.Oinstance
    SPHERE = c4d.Osphere
    EMPTY = c4d.Onull
    BONES = 1019362
    IK = 1019362
    PARTICLES = 1001381
    # PARAMS ID
    PRIM_SPHERE_RAD = 1110

    # MATERIAL ATTRIB
    LAYER = 1011123
    GRADIANT = 1011100
    FUSION = 1011109

    # COMMAND ID
    OPTIMIZE = 14039
    RECORD = 12410
    CONNECT = 12144
    CONNECT_DEL = 16768
    BIND = 1019881
    CREATEIKCHAIN = 1019884
    DESELECTALL = 12113
    SELCHILDREN = 16388
    FITTOVIEW = 430000774
    REVERSE_NORMAL = 14041
    # need an axis dictionary

    # PARTICULE DATA DIC
    CH_DAT_TYPE = {"Real": 19, "String": 130, "Int": 15, "Object": 400006009}

    # dic options
    CAM_OPTIONS = {"ortho": 1, "persp": 0}
    LIGHT_OPTIONS = {"Area": 0, "Sun": 3, "Spot": 1}
    # type of light 0 :omni, 1:spot,2:squarespot,3:infinite,4:parralel,
    # 5:parrallel spot,6:square parral spot 8:area

    # I can record pos/rot/scale and APA for selected object using this commands.
    VERBOSE = 0
    DEBUG = 0
    host = "c4d"
    renderInstance = True

    def __init__(self, master=None, **kw):
        Helper.__init__(self)
        # we can define here some function alias
        self.updateAppli = self.update
        # some synonym,dejaVu compatilbity->should disappear later
        self._render_instance = True
        self.Cube = self.box
        self.Box = self.box
        self.Geom = self.newEmpty
        # self.getCurrentScene = c4d.documents.GetActiveDocument
        self.IndexedPolygons = self.polygons
        self.Points = self.PointCloudObject
        self.hext = "c4d"
        self.synchro_cb = c4dSynchro(helper=self)

        self.noise_type = {
            "boxNoise": c4d.NOISE_BOX_NOISE,
            "buya": c4d.NOISE_BUYA,
            "cellNoise": c4d.NOISE_CELL_NOISE,
            "cellVoronoi": c4d.NOISE_CELL_VORONOI,
            "cranal": c4d.NOISE_CRANAL,
            "dents": c4d.NOISE_DENTS,
            "displacedTurbulence": c4d.NOISE_DISPL_TURB,
            "electrico": c4d.NOISE_ELECTRIC,
            "fbm": c4d.NOISE_FBM,
            "fire": c4d.NOISE_FIRE,
            "gas": c4d.NOISE_GASEOUS,
            "hama": c4d.NOISE_HAMA,
            "luka": c4d.NOISE_LUKA,
            "modNoie": c4d.NOISE_MOD_NOISE,
            "naki": c4d.NOISE_NAKI,
            "noise": c4d.NOISE_NOISE,
            "none": c4d.NOISE_NONE,
            "nutous": c4d.NOISE_NUTOUS,
            "ober": c4d.NOISE_OBER,
            "pezo": c4d.NOISE_PEZO,
            "poxo": c4d.NOISE_POXO,
            "sema": c4d.NOISE_SEMA,
            "sparseConvolution": c4d.NOISE_SPARSE_CONV,
            "stupl": c4d.NOISE_STUPL,
            "turbulence": c4d.NOISE_TURBULENCE,
            "vlNoise": c4d.NOISE_VL_NOISE,
            "voronoi1": c4d.NOISE_VORONOI_1,
            "voronoi2": c4d.NOISE_VORONOI_2,
            "voronoi3": c4d.NOISE_VORONOI_3,
            "wavyTurbulence": c4d.NOISE_WAVY_TURB,
            "zada": c4d.NOISE_ZADA,
        }
        self.track_axis_dic = {
            "-Z": [5, [0., 0., -1]],
            "+Z": [4, [0., 0., 1]],
            "-Y": [3, [0., -1., 0.]],
            "+Y": [2, [0., 1., 0.]],
            "-X": [1, [-1., 0., 0.]],
            "+X": [0, [1., 0., 0.]],
        }
        self.quad = {"+Z": [[-1, -1, 0], [-1, 1, 0], [1, 1, 0], [1, -1, 0], ],  # XY
                     "+Y": [[-1, 0, -1], [-1, 0, 1], [1, 0, 1], [1, 0, -1]],  # XZ
                     "-X": [[0, -1, 1], [0, 1, 1], [0, 1, -1], [0, -1, -1]],  # YZ
                     "-Z": [[-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0]],  # XY
                     "-Y": [[-1, 0, 1], [1, 0, 1], [1, 0, -1], [-1, 0, -1]],  # XZ
                     "+X": [[0, -1, 1], [0, 1, 1], [0, 1, -1], [0, -1, -1]],  # YZ
                     }
        self.eq = {"+X": [self.track_axis_dic["+Y"][1], -math.pi / 2.0],
                   "+Y": [self.track_axis_dic["-X"][1], math.pi / 2.0],
                   "+Z": [self.track_axis_dic["-Z"][1], 0.0],
                   "-X": [self.track_axis_dic["-Y"][1], -math.pi / 2.0],
                   "-Y": [self.track_axis_dic["-X"][1], math.pi / 2.0],
                   "-Z": [self.track_axis_dic["-Z"][1], -math.pi / 2.0]}

    #        eq={"+X":"+Z",
    #            "+Y":"+X",
    #            "+Z":"+Z",
    #            "-X":"+Z",
    #            "-Y":"-X",
    #            "-Z":"+Z"}

    def start_thread(self, job):
        thread = UserThread()
        thread.Start()
        # Do some other operations here
        thread.Wait(True)  #

    def testForEscape(self, ):
        bc = c4d.BaseContainer()
        c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.KEY_ESC, bc)
        return bc.GetLong(c4d.BFM_INPUT_VALUE)

    def synchronize(self, cb):
        self.synchro_cb.add_callback(cb)
        self.synchro_cb.create_str_for_cb()
        self.synchro_cb.set_callback()

    def unsynchronize(self, cb):
        self.synchro_cb.remove_callback(cb)

    #    @classmethod
    def getCurrentScene(self):
        if hasattr(self, "doc"):
            if self.doc.IsAlive():
                return self.doc
            else:
                return c4d.documents.GetActiveDocument()
        else:
            # self.doc = c4d.documents.GetActiveDocument()
            return c4d.documents.GetActiveDocument()

        #    @classmethod

    def getCurrentSceneName(self):
        doc = self.getCurrentScene()
        return doc.GetDocumentName()

    def fit_view3D(self):
        c4d.CallCommand(self.FITTOVIEW)

    def drawQuestion(self, title="", question=""):
        """ Draw a Question message dialog, requiring a Yes/No answer
        @type  title: string
        @param title: the windows title
        @type  question: string
        @param question: the question to display

        @rtype:   bool
        @return:  the answer
        """
        return c4d.gui.QuestionDialog(question)

    def progressBar(self, progress=None, label=None):
        """ update the progress bar status by progress value and label string
        @type  progress: Int/Float
        @param progress: the new progress
        @type  label: string
        @param label: the new message to put in the progress status
        """
        # the progessbar use the StatusSetBar
        if progress is not None:
            c4d.StatusSetBar(progress * 100.)
        if label is not None:
            c4d.StatusSetText(label)
        if progress == 1.0:
            self.resetProgressBar()

    def resetProgressBar(self, value=None):
        """reset the Progress Bar, using value"""
        c4d.StatusClear()

    def update(self):
        # getCurrentScene().GeSyncMessage(c4d.MULTIMSG_UP)
        c4d.DrawViews(c4d.DRAWFLAGS_ONLY_ACTIVE_VIEW | c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_NO_ANIMATION)
        c4d.GeSyncMessage(c4d.EVMSG_TIMECHANGED)
        # c4d.DrawViews(c4d.DRAWFLAGS_NO_THREAD|c4d.DRAWFLAGS_FORCEFULLREDRAW)

    def setCurrentSelection(self, obj):
        # obj have  be c4d.object
        if obj is None:
            return
        if type(obj) is list or type(obj) is tuple:
            self.getCurrentScene().SetSelection(obj[0], c4d.SELECTION_NEW)
            for o in obj[1:]:
                self.getCurrentScene().SetSelection(o, c4d.SELECTION_ADD)
        else:
            self.getCurrentScene().SetSelection(obj, c4d.SELECTION_NEW)
        self.update()

    #        if type(obj) == c4d.BaseObject :
    #            sc.SetSelection(listeObjects[0],c4d.SELECTION_NEW)
    #            self.getCurrentScene().SetActiveObject(obj)

    def getCurrentSelection(self, ):
        """
        Return the current/active selected object in the document or scene

        @rtype:   liste
        @return:  the list of selected object
        """
        return self.getCurrentScene().GetSelection()

    def clearSelection(self, ):
        c4d.CallCommand(self.DESELECTALL)

    def getType(self, object):
        if object is None: return None
        try:
            return object.GetType()
        except:
            return None

    def getMeshFrom(self, obj):
        return self.getMesh(obj)

    def getFirstMesh(self, m, **kw):
        im = True
        if "instance_master" in kw:
            im = kw["instance_master"]
        if m is None:
            return None
        #        print ("getFirstMesh",m,m.GetType(),im)
        if m.GetType() == c4d.Opolygon:
            return m
        elif m.GetType() == c4d.Onull:
            return self.getFirstMesh(m.GetDown(), instance_master=im)
        elif m.GetType() == c4d.Oinstance:
            #            print ("do instance ?",im,m)
            if im:
                return self.getFirstMesh(m[c4d.INSTANCEOBJECT_LINK])
            else:
                #                print ("instance ",m)
                return m
        else:
            # print ("what ? getFirstMesh",m,m.GetType())
            return m  # can be cylinder#cself.getFirstMesh(m.GetDown())

    def getMesh(self, m, **kw):
        im = True  # go until instance master if any
        if "instance_master" in kw:
            im = kw["instance_master"]
        if type(m) is str:
            m = self.getCurrentScene().SearchObject(m)
        if m is not None:
            return self.getFirstMesh(m, instance_master=im)
        else:
            return None

    def getName(self, o):
        if type(o) is str:
            o = self.getObject(o)
        name = ""
        if o is not None:
            try:
                name = o.GetName()
            except:
                # maybe a DejAvu
                try:
                    name = o.name
                except:
                    name = ""
            return name
        else:
            return name

    def getObjectName(self, o, **kw):
        return self.getName(self, o)

    def setName(self, o, name):
        if name is None:
            return
        if type(o) is str:
            o = self.getObject(o)
        o.SetName(name)

    def getObject(self, name):
        obj = None
        if type(name) != str and type(name) != unicode: return name
        #        print "getObject"
        #        print  self.getCurrentScene().GetName()
        try:
            obj = self.getCurrentScene().SearchObject(str(name))
        except:
            obj = None
        return obj

    def getChilds(self, obj):
        if obj is None:
            return None
        if type(obj) == str and type(obj) == unicode:
            obj = self.getObject(obj)
        if hasattr(obj, 'GetChilds'):
            return obj.GetChilds()
        else:
            if hasattr(obj, 'GetChildren'):
                return obj.GetChildren()
            else:
                return obj.GetDown()

    def deleteObject(self, obj):
        sc = self.getCurrentScene()
        currentsel = self.getCurrentSelection()
        try:
            obj = self.getObject(obj)
            # print obj,obj.GetName()
            if obj is None:
                return
            sc.SetActiveObject(obj)
            c4d.CallCommand(100004787)  # delete the obj
        except:
            print "problem deleting ", obj
        # restore the selection
        if currentsel:
            self.ObjectsSelection(currentsel, "new")

    def newEmpty(self, name, location=None, parentCenter=None, display=0, visible=0, **kw):
        empty = c4d.BaseObject(c4d.Onull)
        empty.SetName(name)
        empty[1000] = display
        empty[1001] = 1.0
        if location != None:
            if parentCenter != None:
                location = location - parentCenter
            empty.SetAbsPos(self.FromVec(location))
        parent = None
        if "parent" in kw:
            parent = kw["parent"]
        self.addObjectToScene(self.getCurrentScene(), empty, parent=parent)
        return empty

    def newInstance(self, name, object, location=None, c4dmatrice=None, matrice=None,
                    parent=None, material=None, **kw):
        instance = c4d.BaseObject(c4d.Oinstance)
        instance[1001] = object
        instance.SetName(name)  # .replace(":","_")
        # render instance tag ?
        instance[c4d.INSTANCEOBJECT_RENDERINSTANCE] = self.renderInstance
        if c4dmatrice != None:
            # type of matre
            instance.SetMg(c4dmatrice)
        if matrice != None:
            mx = self.matrix2c4dMat(matrice, transpose=True)
            instance.SetMg(mx)
        if location != None:
            instance.SetAbsPos(self.FromVec(location))
        if material is not None:
            self.assignMaterial(instance, material)
        self.addObjectToScene(None, instance, parent=parent)
        return instance

    def getMasterInstance(self, instance, **kw):
        """
        Return the object use for the instanciation
        """
        instance = self.getObject(instance)
        if self.getType(instance) != self.INSTANCE:
            return None
        return instance[c4d.INSTANCEOBJECT_LINK]

    def updateMasterInstance(self, instance, objects, add=True, hide=True, **kw):
        """
        Update the reference of the passed instance by adding/removing-hiding objects

        * overwrited by children class for each host

        >>> sph = helper.Sphere("sph1")
        >>> instance_sph = helper.newInstance("isph1",sph,location = [10.0,0.0,0.0])


        @type  instance: string/hostObj
        @param instance: name of the instance
        @type  objects: list hostObject/string
        @param objects: the list of object to remove/add to the instance reference
        @type  add: bool
        @param add: if True add the objec else remove
        @type  hide: bool
        @param hide: hide instead of remove
        @type kw: dictionary
        @param kw: you can add your own keyword, but it should be interpreted by all host
        """
        instance = self.getObject(instance)
        newObject = self.getObject(objects[0])
        if self.getType(instance) != self.INSTANCE:
            return None
        instance[c4d.INSTANCEOBJECT_LINK] = newObject

    def newClone(self, name, object, location=None, c4dmatrice=None, matrice=None,
                 parent=None, material=None, **kw):
        clone = object.GetClone()
        clone.SetName(name)  # .replace(":","_")
        if c4dmatrice != None:
            # type of matre
            clone.SetMg(c4dmatrice)
        if matrice != None:
            mx = self.matrix2c4dMat(matrice, transpose=True)
            clone.SetMg(mx)
        if location != None:
            clone.SetAbsPos(self.FromVec(location))
        self.addObjectToScene(None, clone, parent=parent)
        if material is not None:
            self.assignMaterial(clone, material)
        return clone

    def getTrackAxis(self, v):
        for a in self.track_axis_dic:
            if self.FromVec(self.track_axis_dic[a][1]) == self.FromVec(v):
                return self.track_axis_dic[a][0]
        return 0

    def setObjectMatrix(self, object, matrice=None, hostmatrice=None,
                        transpose=False, local=False, **kw):
        if hostmatrice != None:
            # type of matre
            if local:
                object.SetMl(hostmatrice)
            else:
                object.SetMg(hostmatrice)
        else:
            mx = self.matrix2c4dMat(matrice, transpose=transpose)
            if local:
                object.SetMl(mx)
            else:
                object.SetMg(mx)

    def concatObjectMatrix(self, object, matrice, c4dmatrice=None, local=True):
        # local or global?
        cmg = object.GetMg()
        cml = object.GetMl()
        if c4dmatrice != None:
            # type of matrice
            if local:
                object.SetMl(cml * c4dmatrice)
            else:
                object.SetMg(cmg * c4dmatrice)
        else:
            mx = self.matrix2c4dMat(matrice, transpose=False)
            if local:
                object.SetMl(cml * mx)
            else:
                object.SetMg(cmg * mx)

    def GetAbsPosUntilRoot(self, obj):
        stop = False
        pos = self.FromVec((0., 0., 0.))
        if obj is None:
            return pos
        parent = obj.GetUp()
        while not stop:
            pos = pos + parent.GetAbsPos()
            parent = parent.GetUp()
            if parent is None:
                stop = True
        return pos

    def addObjectToScene(self, doc, ob, parent=None, centerRoot=True, rePos=None):
        if type(ob) is list:
            obj = ob[0]
        else:
            obj = ob
        if doc is None:
            doc = self.getCurrentScene()
        if self.getObject(obj.GetName()) == None:
            if parent != None:
                if type(parent) == str: parent = self.getObject(parent)
                doc.InsertObject(obj, parent=parent)
                if centerRoot:
                    currentPos = obj.GetAbsPos()
                    if rePos != None:
                        parentPos = self.FromVec(rePos)
                    else:
                        parentPos = self.GetAbsPosUntilRoot(obj)  # parent.GetAbsPos()
                    obj.SetAbsPos(currentPos - parentPos)
            else:
                doc.InsertObject(obj)
        else:
            if parent != None:
                parent = self.getObject(parent)
                self.reParent(obj, parent)
                # add undo support
                # doc.add_undo(c4d.UNDO_NEW, obj)
                # doc.end_undo()

    def AddObject(self, ob, parent=None, centerRoot=True, rePos=None):
        if type(ob) is list:
            obj = ob[0]
        else:
            obj = ob
        doc = self.getCurrentScene()
        # doc.start_undo()
        if self.getObject(obj.GetName()) != None:
            return
        if parent != None:
            if type(parent) == str: parent = self.getObject(parent)
            doc.InsertObject(obj, parent=parent)
            if centerRoot:
                currentPos = obj.GetAbsPos()
                if rePos != None:
                    parentPos = self.FromVec(rePos)
                else:
                    parentPos = self.GetAbsPosUntilRoot(obj)  # parent.GetAbsPos()
                obj.SetAbsPos(currentPos - parentPos)
        else:
            doc.InsertObject(obj)
        # add undo support
        # doc.add_undo(c4d.UNDO_NEW, obj)
        # doc.end_undo()

    def makeHierarchy(self, listObj, listName, makeTagIK=False):
        for i, name in enumerate(listName):
            o = self.getObject(listObj[name])
            if makeTagIK:
                o.MakeTag(IK)
            if i < len(listObj) - 1:
                child = self.getObject(listObj[listName[i + 1]])
                child.InsertUnder(o)

    def addIKTag(self, object):
        object.MakeTag(IK)

    def addCameraToScene(self, name, Type='persp', focal=30.0, center=[0., 0., 0.], sc=None):
        if sc == None:
            sc = self.getCurrentScene()
        cam = c4d.BaseObject(self.CAMERA)
        cam.SetName(name)
        cam.SetAbsPos(self.FromVec(center))
        cam[1001] = self.CAM_OPTIONS[Type]  # 1 #0:perspective, 1 :parrallel
        cam[1000] = float(focal)  # parrallel zoom
        cam[1006] = 2 * float(focal)  # perspective focal
        # rotation?
        cam[904, 1000] = pi / 2.
        self.addObjectToScene(sc, cam, centerRoot=False)
        return cam

    def addLampToScene(self, name, Type='Area', rgb=[1., 1., 1.], dist=25.0, energy=1.0,
                       soft=1.0, shadow=False, center=[0., 0., 0.], sc=None, **kw):
        # type of light 0 :omni, 1:spot,2:squarespot,3:infinite,4:parralel,
        # 5:parrallel spot,6:square parral spot 8:area
        # light sun type is an infinite light with a sun tag type
        lamp = c4d.BaseObject(self.LIGHT)
        lamp.SetName(name)
        lamp.SetAbsPos(self.FromVec(center))
        lamp[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_X] = pi / 2.
        lamp[c4d.LIGHT_COLOR] = c4d.Vector(float(rgb[0]), float(rgb[1]), float(rgb[2]))  # color
        lamp[c4d.LIGHT_BRIGHTNESS] = float(energy)  # intensity
        lamp[c4d.LIGHT_TYPE] = self.LIGHT_OPTIONS[Type]  # type
        if shadow: lamp[c4d.LIGHT_SHADOWTYPE] = 1  # soft shadow map
        if Type == "Sun":
            suntag = lamp.MakeTag(self.SUNTAG)
        self.addObjectToScene(sc, lamp, centerRoot=False)
        return lamp

    def reParent(self, obj, parent):
        if obj == None or parent == None:
            return
        if type(obj) == list or type(obj) == tuple:
            [self.reParent(o, parent) for o in obj]
        else:
            obj = self.getObject(obj)
            parent = self.getObject(parent)

            obj.InsertUnder(parent)
        #            self.getCurrentScene().add_undo(c4d.UNDO_NEW, obj)

    def setInstance(self, name, object, location=None, c4dmatrice=None, matrice=None):
        instance = c4d.BaseObject(c4d.Oinstance)
        instance[1001] = object
        instance.SetName(name)  # .replace(":","_")
        if location != None:
            instance.SetAbsPos(self.FromVec(location))
        if c4dmatrice != None:
            # type of matre
            instance.SetMg(c4dmatrice)
        if matrice != None:
            mx = self.matrix2c4dMat(matrice)
            instance.SetMl(mx)
            p = instance.GetAbsPos()
            instance.SetAbsPos(c4d.Vector(p.y, p.z, p.x))
        return instance

    def getTranslation(self, name, absolue=True):
        obj = self.getObject(name)
        objdcache = obj.GetDeformCache()
        objcache = obj.GetCache()
        if objdcache is not None:
            if absolue:
                m = objdcache.GetMg()
            else:
                m = objdcache.GetMl()
        elif objcache is not None:
            if absolue:
                m = objcache.GetMg()
            else:
                m = objcache.GetMl()
            #            print "trans cache ",m.off
        else:
            if absolue:
                m = obj.GetMg()
            else:
                m = obj.GetMl()
        return m.off

    #        return obj.GetAbsPos()

    def resetTransformation(self, name):
        obj = self.getObject(name)
        objdcache = obj.GetDeformCache()
        objcache = obj.GetCache()
        m = c4d.Matrix()
        if objdcache is not None:
            objdcache.SetMg(m)
        elif objcache is not None:
            objcache.SetMg(m)
        else:
            obj.SetMg(m)

    def getTransformation(self, name):
        obj = self.getObject(name)
        objdcache = obj.GetDeformCache()
        objcache = obj.GetCache()
        if objdcache is not None:
            m = objdcache.GetMg()
        elif objcache is not None:
            m = objcache.GetMg()
        #            print "trans cache ",m.off
        else:
            m = obj.GetMg()
        return m

    def setTranslation(self, name, pos=[0., 0., 0.], absolue=True):
        if absolue:
            self.getObject(name).SetAbsPos(self.FromVec(pos))
        else:
            self.getObject(name).SetRelPos(self.FromVec(pos))

    def translateObj(self, obj, position, use_parent=True):
        if len(position) == 1:
            c = position[0]
        else:
            c = position
        # print "upadteObj"
        newPos = self.FromVec(c)
        if use_parent:
            parentPos = self.GetAbsPosUntilRoot(obj)  # parent.GetAbsPos()
            newPos = newPos - parentPos
            obj.SetAbsPos(newPos)
        else:
            pmx = obj.GetMg()
            mx = c4d.Matrix()
            mx.off = pmx.off + self.FromVec(position)
            obj.SetMg(mx)

    def scaleObj(self, obj, sc):
        if type(sc) is float:
            sc = [sc, sc, sc]
        obj.SetAbsScale(self.FromVec(sc, pos=False))

    def rotateObj(self, obj, rot, **kw):
        # take radians, give degrees
        # should rotate the primitive and not the parent
        primitive = False
        if "primitive" in kw:
            primitive = kw["primitive"]
        if primitive:
            obj = self.getMesh(obj)
        obj[c4d.ID_BASEOBJECT_ROTATION, c4d.VECTOR_X] = float(rot[1])  # rotation about Y #H
        obj[c4d.ID_BASEOBJECT_ROTATION, c4d.VECTOR_Y] = float(rot[2])  # rotation about X #P
        obj[c4d.ID_BASEOBJECT_ROTATION, c4d.VECTOR_Z] = float(rot[0])  # rotation about Z #B

    def getSize(self, obj):
        # take degree
        obj = self.getObject(obj)
        if obj is None:
            return
        return obj[1100]

    def getScale(self, obj):
        return self.ToVec(self.getObject(obj).GetAbsScale(), pos=False)

    def toggleDisplay(self, obj, display, **kw):
        obj = self.getObject(obj)
        if obj is None:
            return
        if self.getType(obj) == self.PARTICLES:
            return
        if display:
            obj.SetEditorMode(c4d.MODE_UNDEF)
        else:
            obj.SetEditorMode(c4d.MODE_OFF)
        if display:
            obj.SetRenderMode(c4d.MODE_UNDEF)
        else:
            obj.SetRenderMode(c4d.MODE_OFF)
        if display:
            obj[906] = 1
        else:
            obj[906] = 0

    def toggleXray(self, object, xray):
        obj = self.getObject(object)
        if obj is None:
            return
        obj[c4d.ID_BASEOBJECT_XRAY] = xray

    def getVisibility(self, obj, editor=True, render=False, active=False):
        # 0 off, 1#on, 2 undef
        display = {0: True, 1: False, 2: True}
        if type(obj) == str:
            obj = self.getObject(obj)
        if editor and not render and not active:
            return display[obj.GetEditorMode()]
        elif not editor and render and not active:
            return display[obj.GetRenderMode()]
        elif not editor and not render and active:
            return bool(obj[906])
        else:
            return display[obj.GetEditorMode()], display[obj.GetRenderMode()], bool(obj[906])

    #####################MATERIALS FUNCTION########################
    def addMaterial(self, name, color):
        import c4d
        import c4d.documents
        name = str(name)
        doc = c4d.documents.GetActiveDocument()
        # create standard material
        __mat = doc.SearchMaterial(name)
        if __mat != None:
            self.colorMaterial(__mat, color)
            return __mat
        else:
            __mat = c4d.BaseMaterial(c4d.Mmaterial)
            # set the default color
            __mat[2100] = c4d.Vector(float(color[0]), float(color[1]), float(color[2]))
            __mat[c4d.ID_BASELIST_NAME] = name  # 900
            # insert the material into the current document
            doc.InsertMaterial(__mat)
            return __mat

    def assignMaterial(self, object, mat, texture=False, **kw):
        if type(object) is list:
            m = mat
            mat = object[0]
            object = m
        if type(mat) is list:
            mat = mat[0]
        tag = object.GetTag(c4d.Ttexture)
        if tag is None:
            tag = object.MakeTag(c4d.Ttexture)
        # check the mat?
        if type(mat) is string:
            mat = self.getCurrentScene().SearchMaterial(mat)
        if mat is not None:
            tag[c4d.TEXTURETAG_MATERIAL] = mat
        if texture:
            tag[c4d.TEXTURETAG_PROJECTION] = 6

    def getMaterialObject(self, o):
        tags = o.GetTags()  # [0]
        # havbe to be sure its Ttexture tag
        mat = []
        for tag in tags:
            if tag.CheckType(c4d.Ttexture):
                mat.append(tag[c4d.TEXTURETAG_MATERIAL])
        return mat

    def getMaterial(self, mat):
        if type(mat) is str:
            return self.getCurrentScene().SearchMaterial(mat)
        else:
            return mat

    def getAllMaterials(self):
        return self.getCurrentScene().GetMaterials()

    def getMaterialName(self, mat):
        return mat[900]

    def createTexturedMaterial(self, name, filename):
        # create the material
        # check if material exist ? update
        Mat = c4d.BaseMaterial(c4d.Mmaterial)
        Mat.SetName(name)
        # link the texture to the material
        text = c4d.BaseList2D(c4d.Xbitmap)
        text[c4d.BITMAPSHADER_FILENAME] = filename
        Mat[c4d.MATERIAL_COLOR_SHADER] = text
        Mat.InsertShader(text)
        Mat.Message(c4d.MSG_UPDATE)
        Mat.Update(True, True)
        c4d.EventAdd()
        c4d.documents.GetActiveDocument().InsertMaterial(Mat)
        return Mat

    def getMaterialProperty(self, material, **kw):
        """
        Change a material properties.

        * overwrited by children class for each host

        @type  material: string/Material
        @param material: the material to modify
            - color
            - specular
            - ...
        """
        mat = self.getMaterial(material)
        res = {}
        if mat is None:
            return
        if "specular" in kw:
            res["specular"] = mat[c4d.MATERIAL_USE_SPECULAR]
        if "specular_color" in kw:
            res["specular_color"] = self.ToVec(mat[c4d.MATERIAL_SPECULAR_COLOR], pos=False)
        if "specular_width" in kw:
            res["specular_width"] = mat[c4d.MATERIAL_SPECULAR_WIDTH]
        if "color" in kw:
            res["color"] = self.ToVec(mat[c4d.MATERIAL_COLOR_COLOR], pos=False)
        if "diffuse" in kw:
            res["diffuse"] = self.ToVec(mat[c4d.MATERIAL_COLOR_COLOR], pos=False)
        return res

    def changeMaterialProperty(self, material, **kw):
        """
        Change a material properties.

        * overwrited by children class for each host

        @type  material: string/Material
        @param material: the material to modify
            - color
            - specular
            - ...
        """
        mat = self.getMaterial(material)
        if mat is None:
            return
        if "specular" in kw:
            if type(kw["specular"]) == bool:
                mat[c4d.MATERIAL_USE_SPECULAR] = kw["specular"]
        if "specular_width" in kw:
            mat[c4d.MATERIAL_SPECULAR_WIDTH] = kw["specular_width"]

    def create_layers_material(self, name):
        import c4d
        import c4d.documents
        # create standard material
        __mat = c4d.BaseMaterial(c4d.Mmaterial)
        __mat[2100] = c4d.Vector(0., 0., 0.)
        __mat[900] = name
        __mat[8000] = c4d.BaseList2D(LAYER)

    def create_loft_material(self, doc=None, name='loft'):
        if doc == None: doc = c4d.documents.GetActiveDocument()
        # c4d.CallCommand(300000109,110)
        GradMat = doc.SearchMaterial('loft')
        if GradMat == None:
            # c4d.documents.load_file(plugDir+'/LoftGradientMaterial1.c4d')
            bd = c4d.documents.MergeDocument(doc, plugDir + '/LoftGradientMaterial1.c4d',
                                             loadflags=c4d.SCENEFILTER_MATERIALS | c4d.SCENEFILTER_MERGESCENE)
            GradMat = doc.SearchMaterial('loft')
            # c4d.CallCommand(300000109,110)-> preset material n110 in the demo version
        # GradMat
        GradMat[2004] = 0  # refletion turn off
        GradMat[2003] = 0  # refletion turn off
        GradMat[8000][1001] = 2001  # type 2d-V
        mat = GradMat.GetClone()
        mat[900] = name
        # grad=mat[8000][1007]
        # grad.delete_all_knots()
        # mat[8000][1007]=grad
        doc.InsertMaterial(mat)
        # mat = create_gradiant_material(doc=doc,name=name)
        return mat

    def create_gradiant_material(self, doc=None, name='grad'):
        if doc == None: doc = c4d.documents.GetActiveDocument()
        mat = c4d.BaseMaterial(c4d.Mmaterial)
        mat[900] = name
        # grad = c4d.Gradient()
        shader = c4d.BaseList2D(GRADIANT)
        mat[8000] = shader
        # mat[8000][1007] = grad
        mat[2004] = 0  # refletion turn off
        mat[2003] = 0  # refletion turn off
        mat[8000][1001] = 2001  # type 2d-V
        doc.InsertMaterial(mat)
        return mat

    def create_environment(self, type, **kw):
        Environment = c4d.BaseObject(c4d.Oenvironment)
        if type == "depthQ":
            Environment[c4d.ENVIRONMENT_AMBIENT] = self.FromVec((1., 1., 1.))
            Environment[c4d.ENVIRONMENT_AMBIENTSTRENGTH] = 1.0
            Environment[c4d.ENVIRONMENT_FOGENABLE] = 1
            Environment[c4d.ENVIRONMENT_FOG] = self.FromVec((1., 1., 1.))
            Environment[c4d.ENVIRONMENT_FOGSTRENGTH] = 1.0
            if kw.has_key('distance'):
                Environment[c4d.ENVIRONMENT_FOGDISTANCE] = kw['distance']
            Environment.SetName(type)
            self.AddObject(Environment)

    def updateRTSpline(self, spline, selectedPoint, distance=2.0,
                       DistanceBumping=1.85):
        # from Graham code
        # print "before loop"
        nb_points = spline.GetPointCount()
        for j in xrange(selectedPoint, nb_points - 1):
            leaderB = spline.GetPointAll(j)
            myPos = spline.GetPointAll(j + 1)
            deltaB = myPos - leaderB
            newPosB = leaderB + deltaB * distance / deltaB.len()
            newPosA = c4d.Vector(0., 0., 0.)
            k = j
            while k >= 0:
                leaderA = spline.GetPointAll(k)
                deltaA = myPos - leaderA;
                if (deltaA.len() <= DistanceBumping and deltaA.len() > 0):
                    newPosA = ((DistanceBumping - deltaA.len()) * deltaA / deltaA.len());
                newPos = newPosB + newPosA
                spline.SetPoint(j + 1, newPos)
                k = k - 1
        jC = selectedPoint;
        while jC > 0:
            leaderBC = spline.GetPointAll(jC);
            myPosC = spline.GetPointAll(jC - 1);
            deltaC = myPosC - leaderBC;
            newPosBC = leaderBC + deltaC * distance / deltaC.len();
            newPosAC = c4d.Vector(0., 0.0, 0.)
            k = jC
            while k < nb_points:
                leaderAC = spline.GetPointAll(k)
                deltaAC = myPosC - leaderAC;
                if (deltaAC.len() <= DistanceBumping and deltaAC.len() > 0.):
                    newPosAC = ((DistanceBumping - deltaAC.len()) * deltaAC / deltaAC.len());
                newPosC = newPosBC + newPosAC
                spline.SetPoint(jC - 1, newPosC)
                k = k + 1
            jC = jC - 1

    def ObjectsSelection(self, listeObjects, typeSel="new"):
        """
        Modify the current object selection.

        @type  listeObjects: list
        @param listeObjects: list of object to joins
        @type  typeSel: string
        @param listeObjects: type of modification: new,add,...

        """

        dic = {"add": c4d.SELECTION_ADD, "new": c4d.SELECTION_NEW}
        sc = self.getCurrentScene()
        [sc.SetSelection(x, dic[typeSel]) for x in listeObjects]

    def JoinsObjects(self, listeObjects, delete=False):
        """
        Merge the given liste of object in one unique geometry.

        @type  listeObjects: list
        @param listeObjects: list of object to joins
        """
        #        print self.getName(listeObjects[-1])
        #        print self.getName(listeObjects[0])
        self.clearSelection()
        sc = self.getCurrentScene()
        o = self.getObject(self.getName(listeObjects[-1]) + ".1")
        print "get ", o
        if o is not None:
            self.deleteObject(o)
        [self.makeEditable(o, copy=False) for o in listeObjects]
        sc.SetSelection(listeObjects[0], c4d.SELECTION_NEW)
        for i in range(1, len(listeObjects)):
            #            ob = self.makeEditable(listeObjects[i],copy=False)
            #            print listeObjects[i].GetName(),ob.GetName()
            sc.SetSelection(listeObjects[i], c4d.SELECTION_ADD)
            [sc.SetSelection(x, c4d.SELECTION_ADD) for x in self.getChilds(listeObjects[i])]
        c4d.CallCommand(self.SELCHILDREN)
        if delete:
            c4d.CallCommand(self.CONNECT_DEL)
        else:
            c4d.CallCommand(self.CONNECT)

    def getCylinderAxis(self, cyl):
        # return the VECTOR_ indice
        listeAxis = [c4d.VECTOR_X, c4d.VECTOR_X,
                     c4d.VECTOR_Y, c4d.VECTOR_Y,
                     c4d.VECTOR_Z, c4d.VECTOR_Z]
        # cyl = self.getObject(cyl)
        if cyl is None:
            return c4d.VECTOR_Y
        if self.getType(cyl) == self.INSTANCE:
            cyl = cyl[c4d.INSTANCEOBJECT_LINK]
        if self.getType(cyl) != self.CYLINDER:
            cyl = cyl.GetDown()
            if self.getType(cyl) != self.CYLINDER:
                return c4d.VECTOR_Y
        return listeAxis[cyl[c4d.PRIM_AXIS]]

    def setCylinderAxis(self, cyl, axis=0):
        #        listeAxis=[+x,-x,
        #                   +y,-y
        #                   +z,-z]
        cyl = self.getObject(cyl)
        if self.getType(cyl) == self.INSTANCE:
            cyl = cyl[c4d.INSTANCEOBJECT_LINK]
        if self.getType(cyl) != self.CYLINDER:
            cyl = cyl.GetDown()
            if self.getType(cyl) != self.CYLINDER:
                return
        cyl[c4d.PRIM_AXIS] = axis

    def oneCylinder(self, name, head, tail, radius=None, instance=None, material=None,
                    parent=None, color=None):
        laenge, mx = self.getTubeProperties(head, tail)
        if instance is None:
            stick = self.Cylinder(name, parent=parent)[0]
        else:
            stick = c4d.BaseObject(c4d.Oinstance)
            stick[c4d.INSTANCEOBJECT_LINK] = instance
            stick.SetName(name)
            self.addObjectToScene(self.getCurrentScene(), stick, parent=parent)
        stick.SetMg(mx)
        axe = self.getCylinderAxis(stick)
        if radius != None:
            stick[c4d.ID_BASEOBJECT_REL_SCALE] = c4d.Vector(float(radius),
                                                            float(radius), float(radius))
        stick[c4d.ID_BASEOBJECT_REL_SCALE, axe] = float(laenge)  # should scale the axis instead .scale Y
        texture = stick.MakeTag(c4d.Ttexture)
        if material is not None:
            texture[1010] = material
        elif color is not None:
            mat = texture[1010]
            if mat is None:
                mat = self.addMaterial("mat_" + name, color)
                texture[1010] = mat
            else:
                self.colorMaterial(mat, color)
        return stick

    def updateOneCylinder(self, name, head, tail, radius=None, material=None, color=None):
        laenge, mx = self.getTubeProperties(head, tail)
        stick = self.getObject(name)
        stick.SetMg(mx)
        axe = self.getCylinderAxis(stick)
        if radius != None:
            stick[c4d.ID_BASEOBJECT_REL_SCALE] = c4d.Vector(float(radius),
                                                            float(radius), float(radius))
        stick[c4d.ID_BASEOBJECT_REL_SCALE, axe] = float(laenge)  # should scale the axis instead .scale Y
        texture = stick.GetTag(c4d.Ttexture)
        if material == None and color is not None:
            material = self.addMaterial("mat" + name, color)
        if color is not None:
            self.colorMaterial(material, color)
        if material is not None:
            texture[1010] = material
        return stick

    def Cylinder(self, name, radius=1., length=1., res=3, pos=[0., 0., 0.], parent=None, **kw):
        #        QualitySph={"0":16,"1":3,"2":4,"3":8,"4":16,"5":32}
        baseCyl = c4d.BaseObject(self.CYLINDER)
        baseCyl.SetName(name)
        baseCyl[5000] = radius
        baseCyl[5005] = length
        # if str(res) not in QualitySph.keys():
        # Default axes is +Y
        baseCyl[c4d.PRIM_CYLINDER_SEG] = res
        if "axis" in kw:  # orientation
            dic = {"+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5}
            if type(kw["axis"]) is str:
                axis = dic[kw["axis"]]
            else:
                #                axis = dic[self.rerieveAxis([kw["axis"][2],kw["axis"][1],kw["axis"][0]])]
                axis = dic[self.rerieveAxis(kw["axis"])]
            baseCyl[c4d.PRIM_AXIS] = axis
        #        else :#default is +Y
        #            baseCyl[c4d.PRIM_AXIS]=1
        # else :
        #    baseCyl[c4d.PRIM_CYLINDER_SEG] = QualitySph[str(res)]
        # sy.PRIM_CYLINDER_HSUB
        baseCyl.SetAbsPos(self.FromVec(pos))
        baseCyl.MakeTag(c4d.Tphong)
        # addObjectToScene(getCurrentScene(),baseCyl)
        self.addObjectToScene(self.getCurrentScene(), baseCyl, parent=parent)
        return baseCyl, baseCyl

    def Cone(self, name, radius=1., length=1., res=9, pos=[0., 0., 0.], parent=None, **kw):
        baseCone = c4d.BaseObject(self.CONE)
        baseCone.SetName(name)
        baseCone[c4d.PRIM_CONE_TRAD] = 0.
        baseCone[c4d.PRIM_CONE_BRAD] = radius
        baseCone[c4d.PRIM_CONE_HEIGHT] = length
        baseCone[c4d.PRIM_CONE_HSUB] = int(res)
        baseCone[c4d.PRIM_CONE_SEG] = int(3 * res)
        if "axis" in kw:  # orientation
            dic = {"+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5}
            if type(kw["axis"]) is str:
                axis = dic[kw["axis"]]
            else:
                axis = kw["axis"]
            baseCone[c4d.PRIM_AXIS] = axis
        else:
            baseCone[c4d.PRIM_AXIS] = 2  # +Y default
        # else :
        #    baseCyl[c4d.PRIM_CYLINDER_SEG] = QualitySph[str(res)]
        # sy.PRIM_CYLINDER_HSUB
        baseCone.SetAbsPos(self.FromVec(pos))
        baseCone.MakeTag(c4d.Tphong)
        # addObjectToScene(getCurrentScene(),baseCyl)
        self.addObjectToScene(self.getCurrentScene(), baseCone, parent=parent)
        return baseCone, baseCone

    def Sphere(self, name, radius=1.0, res=10, parent=None, color=None, mat=None, pos=[0., 0., 0.]):
        QualitySph = {"0": 6, "1": 4, "2": 5, "3": 6, "4": 8, "5": 16}
        baseSphere = c4d.BaseObject(c4d.Osphere)
        baseSphere[self.PRIM_SPHERE_RAD] = radius
        baseSphere[1111] = res
        baseSphere.MakeTag(c4d.Tphong)
        baseSphere.SetName(name)
        if mat is not None:
            mat = self.getMaterial(mat)
            self.assignMaterial(baseSphere, mat)
        else:
            if color != None:
                # color = [1.,1.,0.]
                mat = self.addMaterial(name, color)
                self.assignMaterial(baseSphere, mat)
        baseSphere.SetAbsPos(self.FromVec(pos))
        self.addObjectToScene(self.getCurrentScene(), baseSphere, parent=parent)
        return [baseSphere, baseSphere]

    def updateSphereMesh(self, mesh, verts=None, faces=None, basemesh=None,
                         scale=1., **kw):
        im = True
        if "instance_master" in kw:
            im = kw["instance_master"]
        mesh = self.getMesh(mesh, instance_master=im)
        print mesh, mesh.GetName(), scale, im
        #        print mesh[905]
        mesh[905] = self.FromVec([scale, scale, scale], pos=False)
        mesh.Message(c4d.MSG_UPDATE)

    def updateSphereObj(self, obj, coord):
        self.updateObjectPos(obj, coord)

    def updateObjectPos(self, object, position):
        object = self.getObject(object)
        if object is None:
            return
        if len(position) == 1:
            c = position[0]
        else:
            c = position
        # print "upadteObj"
        newPos = self.FromVec(c)
        parentPos = self.GetAbsPosUntilRoot(object)  # parent.GetAbsPos()
        object.SetAbsPos(newPos - parentPos)

    #    def clonesAtomsSphere(self,name,x,iMe,doc,mat=None,scale=1.0,
    #                          Res=32,R=None,join=0):
    #        spher=[]
    #        k=0
    #        n='S'
    #        AtmRadi = {"A":1.7,"N":1.54,"C":1.7,"P":1.7,"O":1.52,"S":1.85,"H":1.2}
    #
    #        if scale == 0.0 : scale = 1.0
    #        if mat == None : mat=create_Atoms_materials()
    #        if name.find('balls') != (-1) : n='B'
    #        for j in range(len(x)): spher.append(None)
    #        for j in range(len(x)):
    #            #at=res.atoms[j]
    #            at=x[j]
    #            atN=at.name
    #            #print atN
    #            fullname = at.full_name()
    #            #print fullname
    #            atC=at._coords[0]
    #            spher[j] = iMe[atN[0]].GetClone()
    #            spher[j].SetName(n+"_"+fullname)#.replace(":","_"))
    #            spher[j].SetAbsPos(c4d.Vector(float(atC[2]),float(atC[1]),float(atC[0])))
    #            spher[j][905]=c4d.Vector(float(scale),float(scale),float(scale))
    #            #
    #            #print atN[0]
    #            #print mat[atN[0]]
    #            texture = spher[j].MakeTag(c4d.Ttexture)
    #            texture[1010] = mat[atN[0]]
    #            k=k+1
    #        return spher

    def Spheres(self, name, vertices=[], radii=[], colors=[], **kw):
        """match DejaVu API """
        # need a base sphere
        base = self.Sphere(name + "_base")[0]
        return self.instancesSphere(name, vertices, radii, base,
                                    colors, None)

    def instancesSphere(self, name, centers, radii, meshsphere,
                        colors, scene, parent=None):
        sphs = []
        mat = None
        if len(colors) == 1:
            mat = self.retrieveColorMat(colors[0])
            if mat == None and colors[0] is not None:
                mat = self.addMaterial('mat_' + name, colors[0])
        color_count=0
        for i in range(len(centers)):
            sphs.append(c4d.BaseObject(c4d.Oinstance))
            sphs[i][1001] = meshsphere
            sphs[i].SetName(name + str(i))
            sphs[i].SetAbsPos(self.FromVec(centers[i]))
            # sphs[i].SetAbsPos(c4d.Vector(float(centers[i][0]),float(centers[i][1]),float(centers[i][2])))
            if len(radii) == 1:
                rad = radii[0]
            elif i >= len(radii):
                rad = radii[0]
            else:
                rad = radii[i]
            sphs[i][905] = c4d.Vector(float(rad), float(rad), float(rad))
            texture = sphs[i].MakeTag(c4d.Ttexture)
            # if mat == None :
            if colors is not None and colors[color_count] is not None and len(colors) != 1:
                mat = self.addMaterial(name+"matsp" + str(i), colors[color_count])
            texture[1010] = mat  # mat[bl.retrieveColorName(sphColors[i])]
            self.addObjectToScene(scene, sphs[i], parent=parent)
            color_count+=1
            if (color_count>=len(colors)):
                color_count=0
        return sphs

    def updateInstancesSphere(self, name, sphs, centers, radii, meshsphere,
                              colors, scene, parent=None, delete=True, **kw):
        mat = None
        if len(colors) == 1:
            mat = self.retrieveColorMat(colors[0])
            if mat == None and colors[0] is not None:
                mat = self.addMaterial('mat_' + name, colors[0])
        delete = False
        if "delete" in kw:
            delete = kw["delete"]
        for i in range(len(centers)):
            if len(radii) == 1:
                rad = radii[0]
            elif i >= len(radii):
                rad = radii[0]
            else:
                rad = radii[i]
            if i < len(sphs):
                sphs[i].SetAbsPos(self.FromVec(centers[i]))
                sphs[i][905] = c4d.Vector(float(rad), float(rad), float(rad))
                texture = sphs[i].GetTag(c4d.Ttexture)
                if mat == None:
                    if colors is not None and i < len(colors) and colors[i] is not None:
                        mat = self.addMaterial("matsp" + str(i), colors[i])
                if colors is not None and i < len(colors) and colors[i] is not None:
                    self.colorMaterial(mat, colors[i])
                texture[1010] = mat
                self.toggleDisplay(sphs[i], True)
            else:
                sphs.append(c4d.BaseObject(c4d.Oinstance))
                sphs[i][1001] = meshsphere
                sphs[i].SetName(name + str(i))
                sphs[i].SetAbsPos(self.FromVec(centers[i]))
                sphs[i][905] = c4d.Vector(float(rad), float(rad), float(rad))
                texture = sphs[i].MakeTag(c4d.Ttexture)
                if mat == None:
                    if colors is not None and i < len(colors) and colors[i] is not None:
                        mat = self.addMaterial("matsp" + str(i), colors[i])
                texture[1010] = mat  # mat[bl.retrieveColorName(sphColors[i])]
                self.addObjectToScene(scene, sphs[i], parent=parent)
        if len(centers) < len(sphs):
            # delete the other ones ?
            for i in range(len(centers), len(sphs)):
                if delete:
                    obj = sphs.pop(i)
                    print "delete", obj
                    self.deleteObject(obj)
                else:
                    self.toggleDisplay(sphs[i], False)
        return sphs

    def getTubeProperties(self, coord1, coord2):
        # need ot overwrite in C4D
        # print coord1,coord1[0],type(coord1[0])
        coord1 = self.ToVec(coord1)
        coord2 = self.ToVec(coord2)
        x1 = float(coord1[0])
        y1 = float(coord1[1])
        z1 = float(coord1[2])
        x2 = float(coord2[0])
        y2 = float(coord2[1])
        z2 = float(coord2[2])
        laenge = math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2))
        if laenge == 0.0:
            return 0, c4d.Matrix(c4d.Vector(0), c4d.Vector(1, 0, 0), c4d.Vector(0, 1, 0), c4d.Vector(0, 0, 1))
        wsz = atan2((y1 - y2), (z1 - z2))
        wz = acos((x1 - x2) / laenge)
        offset = c4d.Vector(float(z1 + z2) / 2, float(y1 + y2) / 2, float(x1 + x2) / 2)
        v_2 = c4d.Vector(float(z1 - z2), float(y1 - y2), float(x1 - x2))
        v_2.Normalize()
        v_1 = c4d.Vector(float(1.), float(0.), float(2.))
        v_3 = c4d.Vector.Cross(v_1, v_2)
        v_3.Normalize()
        v_1 = c4d.Vector.Cross(v_2, v_3)
        v_1.Normalize()
        mx = c4d.Matrix(offset, v_1, v_2, v_3)
        return laenge, mx

    def instancesCylinder(self, name, points, faces, radii,
                          mesh, colors, scene, parent=None, **kw):
        cyls = []
        mat = None
        if len(colors) == 1:
            mat = self.retrieveColorMat(colors[0])
            if mat == None and colors[0] is not None:
                mat = self.addMaterial('mat_' + name, colors[0])
        for i in range(len(faces)):
            cyl = self.oneCylinder(name + str(i), points[faces[i][0]],
                                   points[faces[i][1]], radius=radii[i],
                                   instance=mesh, material=mat, parent=parent)
            cyls.append(cyl)
        return cyls

    def updateInstancesCylinder(self, name, cyls, points, faces, radii,
                                mesh, colors, scene, parent=None, delete=True, **kw):
        mat = None
        if len(colors) == 1:
            mat = self.retrieveColorMat(colors[0])
            if mat == None and colors[0] is not None:
                mat = self.addMaterial('mat_' + name, colors[0])
        for i in range(len(faces)):
            col = None
            if i < len(colors):
                col = colors[i]
            if i < len(cyls):
                self.updateOneCylinder(cyls[i], points[faces[i][0]],
                                       points[faces[i][1]], radius=radii[i],
                                       material=mat, color=col)
                self.toggleDisplay(cyls[i], True)
            else:
                cyl = self.oneCylinder(name + str(i), points[faces[i][0]],
                                       points[faces[i][1]], radius=radii[i],
                                       instance=mesh, material=mat, parent=parent)
                cyls.append(cyl)

        if len(faces) < len(cyls) and delete:
            # delete the other ones ?
            for i in range(len(faces), len(cyls)):
                if delete:
                    obj = cyls.pop(i)
                    self.deleteObject(obj)
                else:
                    self.toggleDisplay(cyls[i], False)
        return cyls

    def updateTubeMesh(self, mesh, cradius=1.0, quality=0, **kw):
        # change the radius to cradius
        mesh = self.getMesh(mesh)
        # print mesh.GetName(), cradius
        #        mesh=geom.mesh.GetDown()#should be the cylinder
        # mesh[5000]=cradius
        #        cradius = cradius*1/0.2
        # should used current Y scale too
        axe = self.getCylinderAxis(mesh)  # principal axis
        back = mesh[905]
        #        mesh[905]=mesh[905]^c4d.Vector(float(cradius),1.,float(cradius))
        mesh[905] = c4d.Vector(float(cradius), float(cradius), float(cradius))
        # restore length
        if axe is c4d.VECTOR_X:
            mesh[905, axe] = back.x
        elif axe is c4d.VECTOR_Y:
            mesh[905, axe] = back.y
        elif axe is c4d.VECTOR_Z:
            mesh[905, axe] = back.z
        mesh.Message(c4d.MSG_UPDATE)
        # pass

    def updateTubeObj(self, *args, **kw):  # obj,coord1,coord2,bicyl=False):
        # if self.DEBUG :
        # print "updateTubeObj", args
        o = args[0]
        o = self.getObject(o)
        coord1 = args[1]
        coord2 = args[2]
        laenge, mx = self.getTubeProperties(coord1, coord2)
        o.SetMl(mx)
        o[905, 1001] = float(laenge)
        parentPos = self.GetAbsPosUntilRoot(o)  # parent.GetAbsPos()
        currentPos = o.GetAbsPos()
        o.SetAbsPos(currentPos - parentPos)

    #    def oldTube(set,atms,points,faces,doc,mat=None,res=32,size=0.25,sc=1.,join=0,instance=None,hiera = 'perRes'):
    #     bonds, atnobnd = set.bonds
    #     backbone = ['N', 'CA', 'C', 'O']
    #     stick=[]
    #     tube=[]
    #     #size=size*2.
    #     #coord1=x[0].atms[x[0].atms.CApos()].xyz() #x.xyz()[i].split()
    #     #coord2=x[1].atms[x[1].atms.CApos()].xyz() #x.xyz()[i+1].split()
    #     #print len(points)
    #     #print len(faces)
    #     #print len(atms)
    #     atm1=bonds[0].atom1#[faces[0][0]]
    #     atm2=bonds[0].atom2#[faces[0][1]]
    #     #name="T_"+atm1.name+str(atm1.number)+"_"+atm2.name+str(atm2.number)
    #     name="T_"+atm1.full_name()+"_"+atm2.name
    #     mol=atm1.getParentOfType(Protein)
    #     laenge,mx=getStickProperties(points[faces[0][0]],points[faces[0][1]])
    #     if mat == None : mat=create_sticks_materials()
    #     if instance == None :
    #         stick.append(c4d.BaseObject(CYLINDER))#(res, size, laenge/sc) #1. CAtrace, 0.25 regular |sc=1 CATrace, 2 regular
    #         stick[0].SetMg(mx)
    #         stick[0][5005]=laenge/sc#size
    #         stick[0][5000]=size#radius
    #         stick[0][5008]=res#resolution
    #         stick[0][5006]=2#heght segment
    #     else :
    #         stick.append(c4d.BaseObject(INSTANCE))
    #         stick[0][1001]=instance
    #         stick[0].SetMg(mx)
    #         stick[0][905,1001]=float(laenge)
    #     texture=stick[0].MakeTag(c4d.Ttexture)
    #     #print  atms[faces[0][0]].name[0]+atms[faces[0][1]].name[0]
    #     name1=atms[faces[0][0]].name[0]
    #     name2=atms[faces[0][1]].name[0]
    #     if name1 not in AtmRadi.keys(): name1="A"
    #     if name2 not in AtmRadi.keys(): name2="A"
    #     texture[1010]=mat[name1+name2]
    #     stick[0].SetName(name)
    #     #stick[0].SetAbsPos(c4d.Vector(float(z1+z2)/2,float(y1+y2)/2,float(x1+x2)/2))
    #     #stick[0].set_rot(c4d.Vector(float(wz),float(0),float(wsz)))
    #     #stick[0][904,1000] = wz #RY/RH
    #     #stick[0][904,1002] = wsz #RZ/RB
    #     stick[0].MakeTag(c4d.Tphong)
    #     hierarchy=parseObjectName("B_"+atm1.full_name())
    #     #parent=getObject(mol.geomContainer.masterGeom.chains_obj[hierarchy[1]+"_balls"])
    #     if hiera == 'perRes' :
    #         parent = getObject(mol.geomContainer.masterGeom.res_obj[hierarchy[2]])
    #     elif hiera == 'perAtom' :
    #         if atm1.name in backbone :
    #             parent = getObject(atm1.full_name()+"_bond")
    #         else :
    #             parent = getObject(atm1.full_name()+"_sbond")
    #     else :
    #         parent=getObject(mol.geomContainer.masterGeom.chains_obj[hierarchy[1]+"_balls"])
    #     addObjectToScene(doc,stick[0],parent=parent)
    #     for i in range(1,len(faces)):
    #      atm1=bonds[i].atom1#[faces[i][0]]
    #      atm2=bonds[i].atom2#[faces[i][1]]
    #      #name="T_"+atm1.name+str(atm1.number)+"_"+atm2.name+str(atm2.number)
    #      name="T_"+atm1.full_name()+"_"+atm2.name
    #      laenge,mx=getStickProperties(points[faces[i][0]],points[faces[i][1]])
    #      if instance == None :
    #         stick.append(c4d.BaseObject(CYLINDER))#(res, size, laenge/sc) #1. CAtrace, 0.25 regular |sc=1 CATrace, 2 regular
    #         stick[i].SetMl(mx)
    #         stick[i][5005]=laenge/sc#radius
    #         stick[i][5000]=size#height/size
    #         stick[i][5008]=res#resolution rotation segment
    #         stick[i][5006]=2#heght segment
    #      else :
    #         stick.append(c4d.BaseObject(INSTANCE))
    #         stick[i][1001]=instance
    #         stick[i].SetMl(mx)
    #         stick[i][905,1001]=float(laenge)
    #      texture=stick[i].MakeTag(c4d.Ttexture)
    #      #print i,i+1
    #      name1=atms[faces[i][0]].name[0]
    #      name2=atms[faces[i][1]].name[0]
    #      if name1 not in AtmRadi.keys(): name1="A"
    #      if name2 not in AtmRadi.keys(): name2="A"
    #
    #      if i < len(atms) :
    #         #print  name1+name2
    #         texture[1010]=mat[name1+name2]
    #      else :
    #         texture[1010]=mat[name1+name2]
    #      stick[i].SetName(name)
    #      #stick[i].SetAbsPos(c4d.Vector(float(z1+z2)/2,float(y1+y2)/2,float(x1+x2)/2))
    #      #stick[i].set_rot(c4d.Vector(float(wz),float(0.),float(wsz)))
    #      stick[i].SetMl(mx)
    #      stick[i].MakeTag(c4d.Tphong)
    #      hierarchy=parseObjectName("B_"+atm1.full_name())
    #      #parent=getObject(mol.geomContainer.masterGeom.chains_obj[hierarchy[1]+"_balls"])
    #      if hiera == 'perRes' :
    #         parent = getObject(mol.geomContainer.masterGeom.res_obj[hierarchy[2]])
    #      elif hiera == 'perAtom' :
    #         if atm1.name in backbone :
    #             parent = getObject(atm1.full_name()+"_bond")
    #         else :
    #             parent = getObject(atm1.full_name()+"_sbond")
    #      else :
    #         parent=getObject(mol.geomContainer.masterGeom.chains_obj[hierarchy[1]+"_balls"])
    #
    #      addObjectToScene(doc,stick[i],parent=parent)
    #
    #     #if join==1 :
    #     #    stick[0].join(stick[1:])
    #     #    for ind in range(1,len(stick)):
    #            #obj[0].join([obj[ind]])
    #    #        scn.unlink(stick[ind])
    #        #obj[0].setName(name)
    #     return [stick]
    #
    #

    def FromFace(self, f):
        A = int(f[0])
        B = int(f[1])
        if len(f) == 2:
            C = B
            D = B
            return c4d.CPolygon(C, B, A)
        elif len(f) == 3:
            C = int(f[2])
            D = C
            return c4d.CPolygon(C, B, A)
        elif len(f) == 4:
            C = int(f[2])
            D = int(f[3])
            return c4d.CPolygon(D, C, B, A)

    def FromVec(self, points, pos=True):
        if type(points) == c4d.Vector:
            return points
        if not pos:
            return c4d.Vector(float(points[0]), float(points[1]), float(points[2]))
        else:
            return c4d.Vector(float(points[2]), float(points[1]), float(points[0]))
            # return c4d.Vector(float(points[0]),float(points[1]),float(points[2]))

    def ToVec(self, v, pos=True):
        if type(v) != c4d.Vector:
            return v
        if not pos:
            return [v.x, v.y, v.z]
        else:
            return [v.z, v.y, v.x]

    def getCoordinateMatrix(self, pos, direction):
        offset = pos
        v_2 = direction
        v_2.Normalize()
        v_1 = c4d.Vector(float(1.), float(0.), float(0.))
        v_3 = c4d.Vector.Cross(v_1, v_2)
        v_3.Normalize()
        v_1 = c4d.Vector.Cross(v_2, v_3)
        v_1.Normalize()
        # from mglutil.math import rotax
        # pmx=rotax.rotVectToVect([1.,0.,0.], [float(z1-z2),float(y1-y2),float(x1-x2)], i=None)
        return c4d.Matrix(offset, v_1, v_2, v_3)

    def getCoordinateMatrixBis(self, pos, v1, v2):
        offset = self.FromVec(pos)
        v_2 = self.FromVec(v2)
        v_1 = self.FromVec(v1)
        v_3 = c4d.Vector.Cross(v_1, v_2)
        v_3.Normalize()
        # from mglutil.math import rotax
        # pmx=rotax.rotVectToVect([1.,0.,0.], [float(z1-z2),float(y1-y2),float(x1-x2)], i=None)
        return c4d.Matrix(offset, v_1, v_2, v_3)

    def loftnurbs(self, name, mat=None):
        loft = c4d.BaseObject(self.LOFTNURBS)
        loft[1008] = 0  # adaptive UV false
        loft.SetName(name)
        loft.MakeTag(c4d.Tphong)
        texture = loft.MakeTag(c4d.Ttexture)
        texture[1004] = 6  # UVW Mapping
        # create the dedicayed material
        if mat is not None:
            texture[1010] = mat
        return loft

    def sweepnurbs(self, name, mat=None, parent=None):
        loft = c4d.BaseObject(c4d.Osweep)
        loft.SetName(name)
        loft.MakeTag(c4d.Tphong)
        loft[c4d.SWEEPOBJECT_RAILDIRECTION] = 0
        # create the dedicayed material
        #        if mat == None :
        #                texture[1010] = self.create_loft_material(name='mat_'+name)
        #        else : texture[1010] = mat
        self.addObjectToScene(None, loft, parent=parent)
        if mat is not None:
            texture = loft.MakeTag(c4d.Ttexture)
            texture[1010] = mat
        return loft

    def addShapeToNurb(self, loft, shape, position=-1):
        list_shape = loft.GetChilds()
        shape.insert_after(list_shape[position])

    # def createShapes2D()
    #    sh=c4d.BaseObject(dshape)

    def extrudeSpline(self, spline, **kw):
        extruder = None
        shape = None
        spline_clone = None
        if "extruder" in kw:
            extruder = kw["extruder"]
        if extruder is None:
            extruder = self.sweepnurbs("ex_" + spline.GetName())
        if "shape" in kw:
            if type(kw["shape"]) == str:
                shape = self.build_2dshape("sh_" + kw["shape"] + "_" + spline.GetName(),
                                           kw["shape"])[0]
            else:
                shape = kw["shape"]
        if shape is None:
            shape = self.build_2dshape("sh_circle" + spline.GetName())[0]
        if "clone" in kw and kw["clone"]:
            spline_clone = spline.GetClone()
            self.resetTransformation(spline_clone)
            self.reParent(spline_clone, extruder)
        else:
            self.reParent(spline, extruder)
        self.reParent(shape, extruder)
        if spline_clone is not None:
            return extruder, shape, spline_clone
        return extruder, shape

    def spline(self, name, points, close=0, type=1, extrude_obj=None,
               scene=None, parent=None):
        spline = c4d.BaseObject(c4d.Ospline)
        spline[1000] = type
        spline[1002] = close
        spline.SetName(name)
        spline.ResizeObject(int(len(points)))
        for i, p in enumerate(points):
            spline.SetPoint(i, self.FromVec(p))
        self.addObjectToScene(scene, spline, parent=parent)
        if extrude_obj is not None:
            extruder = self.helper.sweepnurbs(name)
            self.reParent(spline, nurb)
            self.reParent(extrude_obj, nurb)
            return spline, spline, extruder
        return spline, spline

    def update_spline(self, name, new_points):
        spline = self.getObject(name)
        if spline is None:
            return False
        spline.ResizeObject(int(len(new_points)))
        for i, p in enumerate(new_points):
            spline.SetPoint(i, self.FromVec(p))
        spline.Message(c4d.MSG_UPDATE)
        return True

    def build_2dshape(self, name, type="circle", **kw):
        shapedic = {"circle": {"obj": self.CIRCLE, "size": [c4d.PRIM_CIRCLE_RADIUS, ]},
                    "rectangle": {"obj": self.RECTANGLE,
                                  "size": [c4d.PRIM_RECTANGLE_WIDTH, c4d.PRIM_RECTANGLE_HEIGHT]}
                    }
        shape = c4d.BaseObject(shapedic[type]["obj"])
        shape[c4d.PRIM_PLANE] = 0  # 0 XY, 1 ZY, 2 XZ
        dopts = [1., 1.]
        if "opts" in kw:
            dopts = kw["opts"]
        if len(shapedic[type]["size"]) == 1:
            shape[shapedic[type]["size"][0]] = dopts[0]
        else:
            for i in range(len(shapedic[type]["size"])):
                shape[shapedic[type]["size"][i]] = dopts[i]
        self.addObjectToScene(None, shape)
        return shape, None

    def createShapes2Dspline(self, doc=None, parent=None):
        circle = c4d.BaseObject(self.CIRCLE)
        circle[2012] = float(0.3)
        circle[2300] = 1
        if doc: addObjectToScene(doc, circle, parent=parent)
        rectangle = c4d.BaseObject(self.RECTANGLE)
        rectangle[2060] = float(2.2)
        rectangle[2061] = float(0.7)
        rectangle[2300] = 1
        if doc: addObjectToScene(doc, rectangle, parent=parent)
        fourside = c4d.BaseObject(self.FOURSIDE)
        fourside[2121] = float(2.5)
        fourside[2122] = float(0.9)
        fourside[2300] = 1
        if doc: addObjectToScene(doc, fourside, parent=parent)
        shape2D = {}
        pts = [[0, 0, 0], [0, 1, 0], [0, 1, 1], [0, 0, 1]]
        # helixshape
        helixshape = fourside.get_real_spline()  # spline('helix',pts,close=1,type=2)#AKIMA
        helixshape.SetName('helix')
        shape2D['Heli'] = helixshape
        # sheetshape
        sheetshape = rectangle.get_real_spline()  # spline('sheet',pts,close=1,type=0)#LINEAR
        sheetshape.SetName('sheet')
        shape2D['Shee'] = sheetshape
        # strandshape
        strandshape = sheetshape.GetClone()
        strandshape.SetName('strand')
        shape2D['Stra'] = strandshape
        # coilshape
        coilshape = circle.get_real_spline()  # spline('coil',pts,close=1,type=4)#BEZIER
        coilshape.SetName('coil')
        shape2D['Coil'] = coilshape
        # turnshape
        turnshape = coilshape.GetClone()
        turnshape.SetName('turn')
        shape2D['Turn'] = turnshape
        if doc:
            for o in shape2D.values():
                self.addObjectToScene(doc, o, parent=parent)
        return shape2D, [circle, rectangle, fourside, helixshape, sheetshape, strandshape, coilshape, turnshape]

    def constraintLookAt(self, object):
        """
        Cosntraint an hostobject to llok at the camera

        @type  object: Hostobject
        @param object: object to constraint
        """
        self.getObject(object)
        object.MakeTag(self.LOOKATCAM)

    def updateText(self, text, string="", parent=None, size=None, pos=None, font=None,
                   absolue=True):
        text = self.getObject(text)
        if text is None:
            return
        if string: text[c4d.PRIM_TEXT_TEXT] = string
        if size is not None:  text[c4d.PRIM_TEXT_HEIGHT] = size
        if pos is not None: self.setTranslation(text, pos, absolue=absolue)
        if parent is not None: self.reParent(text, parent)

    def Text(self, name="", string="", parent=None, size=5., pos=None, font=None, lookAt=False,
             absolue=True, **kw):
        # extrude options here ?
        return_extruder = False
        text = c4d.BaseObject(self.TEXT)
        text.SetName(name)
        text[c4d.PRIM_TEXT_TEXT] = string  # Text
        text[c4d.PRIM_TEXT_HEIGHT] = size
        # text[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X] = 3.14      #inverse
        text[c4d.PRIM_PLANE] = 1  # ZY
        #        if font is not None:
        #            text[c4d.PRIM_TEXT_FONT]
        if pos is not None:
            self.setTranslation(text, pos, absolue=absolue)
        #        if parent is not None:
        if lookAt:
            self.constraintLookAt(text)
        if "extrude" in kw:
            extruder = None
            # create an extruder
            if type(kw["extrude"]) is bool and kw["extrude"]:
                extruder = c4d.BaseObject(self.EXTRUDER)
                self.addObjectToScene(self.getCurrentScene(), extruder, parent=parent)
                return_extruder = True
            else:
                extruder = kw["extrude"]
            if extruder is not None:
                extruder[c4d.EXTRUDEOBJECT_MOVE] = self.FromVec([0.0, 0., 0.5])  # if x 180.0
                extruder[c4d.EXTRUDEOBJECT_HIERARCHIC] = 1
                parent = extruder
        self.addObjectToScene(self.getCurrentScene(), text, parent=parent)
        if return_extruder:
            return text, extruder
        else:
            return text

    def Circle(self, name, rad=1., **kw):
        circle = c4d.BaseObject(c4d.Osplinecircle)
        circle.SetName(name)
        circle[2012] = float(rad)
        circle[2300] = 0
        parent = None
        if "parent" in kw and kw["parent"] is not None:
            parent = kw["parent"]
        self.addObjectToScene(self.getCurrentScene(), circle, parent=parent)
        return circle

    def createShapes2D(self, doc=None, parent=None):
        if doc is None:
            doc = self.getCurrentScene()
        shape2D = {}
        circle = c4d.BaseObject(self.CIRCLE)
        circle[2012] = float(0.3)
        circle[2300] = 0
        circle.SetName('Circle1')
        circle2 = circle.GetClone()
        circle2.SetName('Circle2')

        coil = c4d.BaseObject(c4d.Onull)
        coil.SetName('coil')
        turn = c4d.BaseObject(c4d.Onull)
        turn.SetName('turn')
        shape2D['Coil'] = coil
        shape2D['Turn'] = turn

        self.addObjectToScene(doc, coil, parent=parent)
        self.addObjectToScene(doc, circle, parent=coil)
        self.addObjectToScene(doc, turn, parent=parent)
        self.addObjectToScene(doc, circle2, parent=turn)

        rectangle = c4d.BaseObject(RECTANGLE)
        rectangle[2060] = float(2.2)
        rectangle[2061] = float(0.7)
        rectangle[2300] = 0
        rectangle.SetName('Rectangle1')
        rectangle2 = rectangle.GetClone()
        rectangle2.SetName('Rectangle2')

        stra = c4d.BaseObject(c4d.Onull)
        stra.SetName('stra')
        shee = c4d.BaseObject(c4d.Onull)
        shee.SetName('shee')
        shape2D['Stra'] = stra
        shape2D['Shee'] = shee

        self.addObjectToScene(doc, stra, parent=parent)
        self.addObjectToScene(doc, rectangle, parent=stra)
        self.addObjectToScene(doc, shee, parent=parent)
        self.addObjectToScene(doc, rectangle2, parent=shee)

        fourside = c4d.BaseObject(FOURSIDE)
        fourside[2121] = float(2.5)
        fourside[2122] = float(0.9)
        fourside[2300] = 0
        heli = c4d.BaseObject(c4d.Onull)
        heli.SetName('heli')
        shape2D['Heli'] = heli

        self.addObjectToScene(doc, heli, parent=parent)
        self.addObjectToScene(doc, fourside, parent=heli)

        return shape2D, [circle, rectangle, fourside]

    def getShapes2D(self):
        shape2D = {}
        shape2D['Coil'] = getObject('coil')
        shape2D['Turn'] = getObject('turn')
        shape2D['Heli'] = getObject('heli')
        shape2D['Stra'] = getObject('stra')
        return shape2D

    def morph2dObject(self, name, objsrc, target):
        obj = objsrc.GetClone()
        obj.SetName(name)
        mixer = obj.MakeTag(self.POSEMIXER)
        mixer[1001] = objsrc  # the default pose
        # for i,sh in enumerate(shape2D) :
        #    mixer[3002,1000+int(i)]=shape2D[sh]
        mixer[3002, 1000] = target  # shape2D[sh] target 1
        return obj

    def c4dSpecialRibon(self, name, points, dshape=CIRCLE, shape2dlist=None, mat=None):
        # if loft == None : loft=loftnurbs('loft',mat=mat)
        shape = []
        pos = c4d.Vector(float(points[0][2]), float(points[0][1]), float(points[0][0]))
        direction = c4d.Vector(float(points[0][2] - points[1][2]), float(points[0][1] - points[1][1]),
                               float(points[0][0] - points[1][0]))
        mx = self.getCoordinateMatrix(pos, direction)
        if shape2dlist:
            shape.append(morph2dObject(dshape + str(0), shape2dlist[dshape], shape2dlist['Heli']))
        else:
            shape.append(c4d.BaseObject(dshape))
            if dshape == self.CIRCLE:
                shape[0][2012] = float(0.3)
                # shape[0][2300]=1
            if dshape == self.RECTANGLE:
                shape[0][2060] = float(0.3 * 4.)
                shape[0][2061] = float(0.3 * 3.)
                # shape[0][2300]=1
            if dshape == self.FOURSIDE:
                shape[0][2121] = float(0.3 * 4.)
                shape[0][2122] = float(0.1)
                # shape[0][2300]=0
        shape[0].SetMg(mx)
        if len(points) == 2: return shape
        i = 1
        while i < (len(points) - 1):
            # print i
            pos = c4d.Vector(float(points[i][2]), float(points[i][1]), float(points[i][0]))
            direction = c4d.Vector(float(points[i - 1][2] - points[i + 1][2]),
                                   float(points[i - 1][1] - points[i + 1][1]),
                                   float(points[i - 1][0] - points[i + 1][0]))
            mx = self.getCoordinateMatrix(pos, direction)
            if shape2dlist:
                shape.append(morph2dObject(dshape + str(i), shape2dlist[dshape], shape2dlist['Heli']))
            else:
                shape.append(c4d.BaseObject(dshape))
                if dshape == self.CIRCLE:
                    shape[i][2012] = float(0.3)
                    shape[i][2300] = 2
                if dshape == self.RECTANGLE:
                    shape[i][2060] = float(0.3 * 4.)
                    shape[i][2061] = float(0.3 * 3.)
                    shape[i][2300] = 2
                if dshape == self.FOURSIDE:
                    shape[i][2121] = float(0.3 * 4.)
                    shape[i][2122] = float(0.1)
                    shape[i][2300] = 2
            shape[i].SetMg(mx)
            i = i + 1
        pos = c4d.Vector(float(points[i][2]), float(points[i][1]), float(points[i][0]))
        direction = c4d.Vector(float(points[i - 1][2] - points[i][2]), float(points[i - 1][1] - points[i][1]),
                               float(points[i - 1][0] - points[i][0]))
        mx = self.getCoordinateMatrix(pos, direction)
        if shape2dlist:
            shape.append(morph2dObject(dshape + str(i), shape2dlist[dshape], shape2dlist['Heli']))
        else:
            shape.append(c4d.BaseObject(dshape))
            if dshape == self.CIRCLE:
                shape[i][2012] = float(0.3)
                shape[i][2300] = 2
            if dshape == self.RECTANGLE:
                shape[i][2060] = float(0.3 * 4.)
                shape[i][2061] = float(0.3 * 3.)
                shape[i][2300] = 2
            if dshape == self.FOURSIDE:
                shape[i][2121] = float(0.3 * 4.)
                shape[i][2122] = float(0.1)
                shape[i][2300] = 2
        shape[i].SetMg(mx)
        return shape

    def c4dSecondaryLofts(self, name, matrices, dshape=CIRCLE, mat=None):
        # if loft == None : loft=loftnurbs('loft',mat=mat)
        shape = []
        i = 0
        while i < (len(matrices)):
            # pos=c4d.Vector(float(points[i][2]),float(points[i][1]),float(points[i][0]))
            # direction=c4d.Vector(float(points[i-1][2]-points[i+1][2]),float(points[i-1][1]-points[i+1][1]),float(points[i-1][0]-points[i+1][0]))
            mx = self.getCoordinateMatrixBis(matrices[i][2], matrices[i][0], matrices[i][1])
            # mx=getCoordinateMatrix(pos,direction)
            shape.append(c4d.BaseObject(dshape))
            shape[i].SetMg(mx)
            if dshape == self.CIRCLE:
                shape[i][2012] = float(0.3)
                shape[i][2300] = 0
            if dshape == self.RECTANGLE:
                shape[i][2060] = float(2.2)
                shape[i][2061] = float(0.7)
                shape[i][2300] = 0
            if dshape == self.FOURSIDE:
                shape[i][2121] = float(2.5)
                shape[i][2122] = float(0.9)
                shape[i][2300] = 0
            i = i + 1
        return shape

    def instanceShape(self, ssname, shape2D):
        # if shape2D=None : shape2D=createShapes2D()
        shape = c4d.BaseObject(c4d.Oinstance)
        shape[1001] = shape2D[ssname[:4]]
        shape.SetName(ssname[:4])
        return shape

    def makeShape(self, dshape, ssname):
        shape = c4d.BaseObject(dshape)
        if dshape == self.CIRCLE:
            shape[2012] = float(0.3)
            shape[2300] = 0
            shape.SetName(ssname[:4])
        if dshape == self.RECTANGLE:
            shape[2060] = float(2.2)
            shape[2061] = float(0.7)
            shape[2300] = 0
            shape.SetName(ssname[:4])
        if dshape == self.FOURSIDE:
            shape[2121] = float(2.5)
            shape[2122] = float(0.9)
            shape[2300] = 0
            shape.SetName(ssname[:4])
        return shape

    def c4dSecondaryLoftsSp(self, name, atoms, dshape=CIRCLE, mat=None, shape2dmorph=None, shapes2d=None,
                            instance=False):
        # print "ok build loft shape"
        # if loft == None : loft=loftnurbs('loft',mat=mat)
        shape = []
        prev = None
        ssSet = atoms[0].parent.parent.secondarystructureset
        molname = atoms[0].full_name().split(":")[0]
        chname = atoms[0].full_name().split(":")[1]
        i = 0
        iK = 0
        # get The pmv-extruder
        sheet = atoms[0].parent.secondarystructure.sheet2D
        matrices = sheet.matrixTransfo
        if mat == None: mat = c4d.documents.GetActiveDocument().SearchMaterial('mat_loft' + molname + '_' + chname)
        while i < (len(atoms)):
            ssname = atoms[i].parent.secondarystructure.name
            dshape = SSShapes[ssname[:4]]  # ssname[:4]
            # print ssname,dshape
            # pos=c4d.Vector(float(points[i][2]),float(points[i][1]),float(points[i][0]))
            # direction=c4d.Vector(float(points[i-1][2]-points[i+1][2]),float(points[i-1][1]-points[i+1][1]),float(points[i-1][0]-points[i+1][0]))
            mx = self.getCoordinateMatrixBis(matrices[i][2], matrices[i][0], matrices[i][1])
            # mx=getCoordinateMatrix(pos,direction)
            # iK=iK+1
            if shape2dmorph:
                shape.append(self.morph2dObject(dshape + str(i), shape2dmorph[dshape], shape2dmorph['Heli']))
                shape[-1].SetMg(mx)
            else:
                # print str(prev),ssname
                if prev != None:  # end of loop
                    if ssname[:4] != prev[:4]:
                        if not instance:
                            shape.append(self.makeShape(SSShapes[prev[:4]], prev))
                        else:
                            shape.append(self.instanceShape(prev, shapes2d))
                        shape[-1].SetMg(mx)
                if not instance:
                    shape.append(self.makeShape(dshape, ssname))
                else:
                    shape.append(self.instanceShape(ssname, shapes2d))
                shape[-1].SetMg(mx)
            prev = ssname
            i = i + 1
        if mat != None:
            prev = None
            # i=(len(shape))
            i = 0
            while i < (len(shape)):
                ssname = shape[i].GetName()
                # print ssname
                pos = 1 - ((((i) * 100.) / len(shape)) / 100.0)
                if pos < 0: pos = 0.
                # print pos
                # change the material knote according ss color / cf atom color...
                # col=atoms[i].colors['secondarystructure']
                col = self.c4dColor(SSColor[ssname])
                nc = c4d.Vector(col[0], col[1], col[2])
                ncp = c4d.Vector(0, 0, 0)
                if prev != None:
                    pcol = self.c4dColor(SSColor[prev])
                    ncp = c4d.Vector(pcol[0], pcol[1], pcol[2])
                    # print col
                # print ssname[:4]
                # print prev
                if ssname != prev:  # new ss
                    grad = mat[8000][1007]
                    # iK=iK+1
                    nK = grad.GetKnotCount()
                    # print "knot count ",nK,iK
                    if iK >= nK:
                        # print "insert ",pos,nK
                        # print "grad.insert_knot(c4d.Vector("+str(col[0])+str(col[1])+str(col[2])+"), 1.0, "+str(pos)+",0.5)"
                        if prev != None:
                            grad.InsertKnot(ncp, 1.0, pos + 0.01, 0.5)
                            iK = iK + 1
                        grad.InsertKnot(nc, 1.0, pos - 0.01, 0.5)
                        # grad.insert_knot(ncp, 1.0, pos+0.1,0.5)
                        iK = iK + 1
                    else:
                        # print "set ",iK,pos
                        if prev != None: grad.SetKnot(iK - 1, ncp, 1.0, pos, 0.5)
                        grad.SetKnot(iK, nc, 1.0, pos, 0.5)
                    mat[8000][1007] = grad
                prev = ssname
                mat.Message(c4d.MSG_UPDATE)
                i = i + 1
                # mx=getCoordinateMatrixBis(matrices[i][2],matrices[i][0],matrices[i][1])
        # if shape2dlist : shape.append(morph2dObject(dshape+str(i),shape2dlist[shape],shape2dlist['Heli']))
        return shape

    def LoftOnSpline(self, name, chain, atoms, Spline=None, dshape=CIRCLE, mat=None,
                     shape2dmorph=None, shapes2d=None, instance=False):
        # print "ok build loft/spline"
        molname = atoms[0].full_name().split(":")[0]
        chname = atoms[0].full_name().split(":")[1]
        # we first need the spline
        # if loft == None : loft=loftnurbs('loft',mat=mat)
        shape = []
        prev = None
        # mol = atoms[0].top
        ssSet = chain.secondarystructureset  # atoms[0].parent.parent.secondarystructureset
        i = 0
        iK = 0
        # get The pmv-extruder
        sheet = chain.residues[0].secondarystructure.sheet2D
        matrices = sheet.matrixTransfo
        ca = atoms.get('CA')
        o = atoms.get('O')
        if Spline is None:
            parent = atoms[0].parent.parent.parent.geomContainer.masterGeom.chains_obj[chname]
            Spline, ospline = spline(name + 'spline', ca.coords)  #
            addObjectToScene(getCurrentScene(), Spline, parent=parent)
            # loftname = 'loft'+mol.name+'_'+ch.name
        # matloftname = 'mat_loft'+mol.name+'_'+ch.name
        if mat == None:
            mat = c4d.documents.GetActiveDocument().SearchMaterial('mat_loft' + molname + '_' + chname)
            if mat is not None:
                if DEBUG: print "ok find mat"
                # if mat == None :
                #    mat = create_loft_material(name='mat_loft'+molname+'_'+chname)
        if DEBUG: print "CA", len(ca)
        while i < (len(ca)):
            pos = float(((i * 1.) / len(ca)))
            # print str(pos)+" %"
            # print atoms[i],atoms[i].parent,hasattr(atoms[i].parent,'secondarystructure')
            if hasattr(ca[i].parent, 'secondarystructure'):
                ssname = ca[i].parent.secondarystructure.name
            else:
                ssname = "Coil"
            dshape = SSShapes[ssname[:4]]  # ssname[:4]
            # mx =getCoordinateMatrixBis(matrices[i][2],matrices[i][0],matrices[i][1])
            # have to place the shape on the spline
            if shape2dmorph:
                shape.append(morph2dObject(dshape + str(i), shape2dmorph[dshape], shape2dmorph['Heli']))
                path = shape[i].MakeTag(Follow_PATH)
                path[1001] = Spline
                path[1000] = 0  # tangantial
                path[1003] = pos
                path[1007] = 2  # 1        axe
                # shape[-1].SetMg(mx)
            else:
                # print str(prev),ssname
                # if prev != None: #end of loop
                #    if ssname[:4] != prev[:4]: #newSS need transition
                #        if not instance : shape.append(makeShape(SSShapes[prev[:4]],prev))
                #        else : shape.append(instanceShape(prev,shapes2d))
                #        #shape[-1].SetMg(mx)
                #        path=shape[-1].MakeTag(Follow_PATH)
                #        path[1001] = Spline
                #        path[1000] = 1
                #        path[1003] = pos
                if not instance:
                    shape.append(makeShape(dshape, ssname))
                else:
                    shape.append(instanceShape(ssname, shapes2d))
                path = shape[i].MakeTag(Follow_PATH)
                path[1001] = Spline
                path[1000] = 0
                path[1003] = pos
                path[1007] = 2  # 1
                # shape[-1].SetMg(mx)
            if i >= 1:
                laenge, mx = getStickProperties(ca[i].coords, ca[i - 1].coords)
                # if i > len(o) : laenge,mx=getStickProperties(ca[i].coords,o[i-1].coords)
                # else :laenge,mx=getStickProperties(ca[i].coords,o[i].coords)
                shape[i].SetMg(mx)
            prev = ssname
            i = i + 1
        laenge, mx = getStickProperties(ca[0].coords, ca[1].coords)
        # laenge,mx=getStickProperties(ca[0].coords,o[0].coords)
        shape[0].SetMg(mx)
        if False:  # (mat != None):
            prev = None
            # i=(len(shape))
            i = 0
            while i < (len(shape)):
                ssname = shape[i].GetName()
                # print ssname
                pos = 1 - ((((i) * 100.) / len(shape)) / 100.0)
                if pos < 0: pos = 0.
                # print pos
                # change the material knote according ss color / cf atom color...
                # col=atoms[i].colors['secondarystructure']
                col = c4dColor(SSColor[ssname])
                nc = c4d.Vector(col[0], col[1], col[2])
                ncp = c4d.Vector(0, 0, 0)
                if prev != None:
                    pcol = c4dColor(SSColor[prev])
                    ncp = c4d.Vector(pcol[0], pcol[1], pcol[2])
                    # print col
                # print ssname[:4]
                # print prev
                if ssname != prev:  # new ss
                    grad = mat[8000][1007]
                    # iK=iK+1
                    nK = grad.GetKnotCount()
                    # print "knot count ",nK,iK
                    if iK >= nK:
                        # print "insert ",pos,nK
                        # print "grad.insert_knot(c4d.Vector("+str(col[0])+str(col[1])+str(col[2])+"), 1.0, "+str(pos)+",0.5)"
                        if prev != None:
                            grad.InsertKnot(ncp, 1.0, pos + 0.01, 0.5)
                            iK = iK + 1
                        grad.InsertKnot(nc, 1.0, pos - 0.01, 0.5)
                        # grad.insert_knot(ncp, 1.0, pos+0.1,0.5)
                        iK = iK + 1
                    else:
                        # print "set ",iK,pos
                        if prev != None: grad.SetKnot(iK - 1, ncp, 1.0, pos, 0.5)
                        grad.SetKnot(iK, nc, 1.0, pos, 0.5)
                    mat[8000][1007] = grad
                prev = ssname
                mat.Message(c4d.MSG_UPDATE)
                i = i + 1
                # mx=getCoordinateMatrixBis(matrices[i][2],matrices[i][0],matrices[i][1])
        # if shape2dlist : shape.append(morph2dObject(dshape+str(i),shape2dlist[shape],shape2dlist['Heli']))
        return shape

    def update_2dsheet(shapes, builder, loft):
        dicSS = {'C': 'Coil', 'T': 'Turn', 'H': 'Heli', 'E': 'Stra', 'P': 'Coil'}
        shape2D = getShapes2D()
        for i, ss in enumerate(builder):
            if shapes[i].GetName() != dicSS[ss]:
                shapes[i][1001] = shape2D[dicSS[ss]]  # ref object
                shapes[i].SetName(dicSS[ss])

        texture = loft.GetTags()[0]
        mat = texture[1010]
        grad = mat[8000][1007]
        grad.delete_all_knots()
        mat[8000][1007] = grad

        prev = None
        i = 0
        iK = 0
        while i < (len(shapes)):
            ssname = shapes[i].GetName()
            # print ssname
            pos = 1 - ((((i) * 100.) / len(shapes)) / 100.0)
            if pos < 0: pos = 0.
            # print pos
            # change the material knote according ss color / cf atom color...
            # col=atoms[i].colors['secondarystructure']
            col = c4dColor(SSColor[ssname])
            nc = c4d.Vector(col[0], col[1], col[2])
            ncp = c4d.Vector(0, 0, 0)
            if prev != None:
                pcol = c4dColor(SSColor[prev])
                ncp = c4d.Vector(pcol[0], pcol[1], pcol[2])
                # print col
            # print ssname[:4]
            # print prev
            if ssname != prev:  # new ss
                grad = mat[8000][1007]
                # iK=iK+1
                nK = grad.get_knot_count()
                # print "knot count ",nK,iK
                if iK >= nK:
                    # print "insert ",pos,nK
                    # print "grad.insert_knot(c4d.Vector("+str(col[0])+str(col[1])+str(col[2])+"), 1.0, "+str(pos)+",0.5)"
                    if prev != None:
                        grad.insert_knot(ncp, 1.0, pos + 0.01, 0.5)
                        iK = iK + 1
                    grad.insert_knot(nc, 1.0, pos - 0.01, 0.5)
                    # grad.insert_knot(ncp, 1.0, pos+0.1,0.5)
                    iK = iK + 1
                else:
                    # print "set ",iK,pos
                    if prev != None: grad.set_knot(iK - 1, ncp, 1.0, pos, 0.5)
                    grad.set_knot(iK, nc, 1.0, pos, 0.5)
                mat[8000][1007] = grad
            prev = ssname
            mat.Message(c4d.MSG_UPDATE)
            i = i + 1

    def makeLines(self, name, points, faces, parent=None):
        rootLine = self.newEmpty(name)
        self.addObjectToScene(self.getCurrentScene(), rootLine, parent=parent)
        spline = c4d.BaseObject(c4d.Ospline)
        # spline[1000]=type
        # spline[1002]=close
        spline.SetName(name + 'mainchain')
        spline.ResizeObject(int(len(points)))
        cd4vertices = map(self.FromVec, points)
        map(polygon.SetPoint, range(len(points)), cd4vertices)
        # for i,p in enumerate(points):
        #    spline.SetPoint(i, c4dv(p))
        self.addObjectToScene(self.getCurrentScene(), spline, parent=rootLine)
        spline = c4d.BaseObject(c4d.Ospline)
        # spline[1000]=type
        # spline[1002]=close
        spline.SetName(name + 'sidechain')
        spline.ResizeObject(int(len(points)))
        for i, p in enumerate(points):
            spline.SetPoint(i, self.FromVec(p))
        self.addObjectToScene(self.getCurrentScene(), spline, parent=rootLine)

    def updateLines(self, lines, chains=None):
        # lines = getObject(name)
        # if lines == None or chains == None:
        # print lines,chains
        # parent = getObject(chains.full_name())
        # print parent
        #    bonds, atnobnd = chains.residues.atoms.bonds
        #    indices = map(lambda x: (x.atom1._bndIndex_,
        #                                x.atom2._bndIndex_), bonds)
        #    updatePoly(lines,vertices=chains.residues.atoms.coords,faces=indices)
        self.updatePoly(self, lines, vertices=chains.residues.atoms.coords)

    #    def getCoordByAtomType(chain):
    #        dic={}
    #        #extract the different atomset by type
    #        for i,atms in enumerate(AtomElements.keys()):
    #            atomset = chain.residues.atoms.get(atms)
    #            bonds, atnobnd = atomset.bonds
    #            indices = map(lambda x: (x.atom1._bndIndex_,
    #                                 x.atom2._bndIndex_), bonds)
    #            dic[atms] = [atomset]
    #
    #    def stickballASmesh(molecules,atomSets):
    #        bsms=[]
    #        for mol, atms, in map(None, molecules, atomSets):
    #            for ch in mol.chains:
    #                parent = getObject(ch.full_name())
    #                lines = getObject(ch.full_name()+'_bsm')
    #                if lines == None :
    #                    lines=newEmpty(ch.full_name()+'_bsm')
    #                    addObjectToScene(getCurrentScene(),lines,parent=parent)
    #                    dic = getCoordByAtomType(ch)
    #                    for type in dic.keys():
    #                        bsm = createsNmesh(ch.full_name()+'_bsm'+type,dic[type][0],
    #                                         None,dic[type][1])
    #                        bsms.append(bsm)
    #                        addObjectToScene(getCurrentScene(),bsm,parent=lines)

    #    def editLines(molecules,atomSets):
    #        for mol, atms, in map(None, molecules, atomSets):
    #            #check if line exist
    #            for ch in mol.chains:
    #                parent = getObject(ch.full_name())
    #                lines = getObject(ch.full_name()+'_line')
    #                if lines == None :
    #                    arr = c4d.BaseObject(ATOMARRAY)
    #                    arr.SetName(ch.full_name()+'_lineds')
    #                    arr[1000] = 0.1 #radius cylinder
    #                    arr[1001] = 0.1 #radius sphere
    #                    arr[1002] = 3 #subdivision
    #                    addObjectToScene(getCurrentScene(),arr,parent=parent)
    #                    bonds, atnobnd = ch.residues.atoms.bonds
    #                    indices = map(lambda x: (x.atom1._bndIndex_,
    #                                             x.atom2._bndIndex_), bonds)
    #
    #                    lines = createsNmesh(ch.full_name()+'_line',ch.residues.atoms.coords,
    #                                         None,indices)
    #                    addObjectToScene(getCurrentScene(),lines[0]    ,parent=arr)
    #                    mol.geomContainer.geoms[ch.full_name()+'_line'] = lines
    #                    #display using AtomArray
    #                else : #need to update
    #                    updateLines(lines, chains=ch)


    def matrixToEdgeMesh(self, name, matrices, **kw):  # edge size ?
        pt1 = [0., -5., 0.]
        pt2 = [0., 5., 0.]  # edgelength
        v = []
        f = []
        e = []
        i = 0
        for m in matrices:
            p1, p2 = self.ApplyMatrix([pt1, pt2], m)
            v.extend([p1, p2])  # edge we want
            e.append([i, i + 1])
            i += 2
            # everyt thre matrices make tow triangle ?
            face1 = [i, i + 1, i + 2]
            face2 = [i, i + 3, i + 4]
            f.extend([face1, face2])
        # need to create triangle
        obj = c4d.PolygonObject(len(v), 0)
        obj.SetName(name)
        cd4vertices = map(self.FromVec, v)
        # map(obj.SetPoint,range(len(v)),cd4vertices)
        [obj.SetPoint(k, self.FromVec(av)) for k, av in enumerate(v)]
        [obj.SetPolygon(k, self.FromFace(af)) for k, af in enumerate(f)]
        c4d.EventAdd()
        #        vtag.SetName(tagName)
        self.addObjectToScene(self.getCurrentScene(), obj)
        if 'parent' in kw and kw['parent'] is not None:
            parent = self.getObject(kw['parent'])
            obj.parent = parent
        return obj, me

    def matrixToVNMesh(self, name, matrices, vector=[0., 1., 0.], **kw):  # edge size ?
        # blender user verex normal for rotated the instance
        pt1 = [0., 0., 0.]  # pos
        pt2 = vector  # [0.,1.,0.]#normal should be given ?
        v = []
        f = []
        e = []
        n = []
        #        i=0
        #       why -90 ?
        for m in matrices:
            #            p1=m[:3, 3]
            #            m[:3, 3]=[0.,0.,0.]
            p1, p2 = self.ApplyMatrix([pt1, pt2], m)
            v.append(p1)
            n.append(p2)
        #            i+=2
        obj = c4d.PolygonObject(len(v), 0)
        obj.SetName(name)
        cd4vertices = map(self.FromVec, v)
        map(obj.SetPoint, range(len(v)), cd4vertices)
        vtag = c4d.NormalTag(len(v))  # starting c4d R13
        obj.InsertTag(vtag)
        c4d.EventAdd()
        vcnt = vtag.GetDataCount()
        # get the pointer to the vertex map array
        vmap = vtag.GetAllHighlevelData()
        vmap = [no for no in n]
        #            vmap=map(lambda x,y,j=j: setVColor(x,j,y),vmap,vcolors)
        vtag.SetAllHighlevelData(vmap)
        vtag.Message(c4d.MSG_UPDATE)
        c4d.EventAdd()
        #        vtag.SetName(tagName)
        self.addObjectToScene(self.getCurrentScene(), obj)
        for i, v in enumerate(points):
            v.normal = self.FromVec(n[i])
        if 'parent' in kw and kw['parent'] is not None:
            parent = self.getObject(kw['parent'])
            obj.parent = parent
        return obj, me

    def transposeMatrix(self, matrice):
        if matrice is not None:
            matrice = numpy.array(matrice)
            if isinstance(matrice, numpy.ndarray):
                mat = matrice.transpose().tolist()
                return mat
            else:
                return matrice  # = mat#numpy.array(matrice)
            #            blender_mat=mathutils.Matrix(mat)#from Blender.Mathutils
            #            blender_mat.transpose()
            #            return blender_mat
        return matrice

    def matrixToFaces(self, name, matrices, vector=[0., 1., 0.], transpose=True, **kw):  # edge size ?
        av = [vector[0], vector[1], vector[2]]
        #        av=[vector[2],vector[1],vector[0]]
        axe = self.rerieveAxis(av)
        # axe="+Y"

        quad = numpy.array(self.quad[axe]) * 10.0
        mX = self.rotation_matrix(self.eq[axe][1], self.eq[axe][0])
        quad = self.ApplyMatrix(quad, mX)
        #        av=self.rotatePoint(av,[0.,0.,0.],[1.0,0.0,0.0,math.pi/2.0])
        # rotate the quad onlong cross.
        #        av=self.rotatePoint([vector[2],vector[1],vector[0]],[0.,0.,0.],[0.0,1.0,0.0,-math.pi/2.0])
        print ("matrixToFacesMesh", axe, av, vector, quad)
        rnorm = False
        if axe[0] == "-":
            rnorm = True
        #        f=[0,1,2,3]
        v = []
        f = []
        e = []
        n = []
        vi = 0
        for i, m in enumerate(matrices):
            if transpose:
                m = self.transposeMatrix(m)
            new_quad = self.ApplyMatrix(quad, m)
            v.extend(new_quad)
            f.append([i * 4 + 0, i * 4 + 1, i * 4 + 2, i * 4 + 3])
        return v, f, rnorm

    def matrixToFacesMesh(self, name, matrices, vector=[0., 1., 0.], transpose=True, **kw):  # edge size ?
        # blender user verex normal for rotated the instance
        # quad up vector should use the inpu vector
        # from Vector ?
        # quad local axis is X-Y->-Z,should rotate
        v, f, rnorm = self.matrixToFaces(name, matrices, vector=vector, transpose=transpose, **kw)
        polygon = c4d.PolygonObject(len(v), len(f))
        polygon.SetName(name + "_me")
        [polygon.SetPoint(k, self.FromVec(vv)) for k, vv in enumerate(v)]
        [polygon.SetPolygon(k, self.FromFace(ff)) for k, ff in enumerate(f)]

        polygon.Message(c4d.MSG_UPDATE)
        c4d.EventAdd()
        self.addObjectToScene(None, polygon)
        self.toggleDisplay(polygon, False)
        if 'parent' in kw and kw['parent'] is not None:
            self.reParent(polygon, kw['parent'])
        if rnorm == True:
            # select it
            self.setCurrentSelection([polygon])
            c4d.CallCommand(self.REVERSE_NORMAL)
            polygon.Message(c4d.MSG_UPDATE)
            c4d.EventAdd()
        return polygon, polygon

    def PointCloudObject(self, name, **kw):
        # need to add the AtomArray modifier....
        pointWidth = 0.1
        doatom = True
        if kw.has_key("pointWidth"):
            pointWidth = float(kw["pointWidth"])
        if kw.has_key("parent"):
            parent = kw["parent"]
        else:
            parent = None
        if kw.has_key("atomarray"):
            doatom = kw["atomarray"]
        if doatom:
            atom = c4d.BaseObject(c4d.Oatomarray)
            atom.SetName(name + "ds")
            atom[1000] = 0.  # radius cylinder
            atom[1001] = pointWidth  # radius sphere
            atom[1002] = 3  # subdivision
            self.addObjectToScene(self.getCurrentScene(), atom, parent=parent)
            parent = atom
        if kw.has_key("materials"):
            texture = parent.MakeTag(c4d.Ttexture)
            texture[1010] = self.addMaterial("mat" + name, kw["materials"][0])
        coords = kw['vertices']
        nface = 0
        if kw.has_key("faces"):
            nface = len(kw['faces'])
        visible = 1
        if kw.has_key("visible"):
            visible = kw['visible']
        obj = c4d.PolygonObject(len(coords), nface)
        obj.SetName(name)
        cd4vertices = map(self.FromVec, coords)
        map(obj.SetPoint, range(len(coords)), cd4vertices)
        # for k,v in enumerate(coords) :
        #    obj.SetPoint(k, c4dv(v))
        self.addObjectToScene(self.getCurrentScene(), obj, parent=parent)
        if parent is not None:
            self.toggleDisplay(parent, bool(visible))
        if doatom:
            return obj, atom
        else:
            return obj, None

    def PolygonColorsObject(self, name, vertColors):
        obj = c4d.PolygonObject(len(vertColors), len(vertColors) / 2.)
        obj.SetName(name + '_color')
        cd4vertices = map(self.FromVec, vertColors)
        map(obj.SetPoint, range(len(vertColors)), cd4vertices)
        # for k,v in enumerate(vertColors) :
        #      obj.SetPoint(k, c4dv(v))
        return obj

    def updatePoly(self, polygon, faces=None, vertices=None):
        if type(polygon) == str:
            polygon = self.getObject(polygon)
        if polygon == None: return
        # check if polygon
        if self.getType(polygon) != self.POLYGON:
            # try to get the childs
            polygon = polygon.GetDown()
            if self.getType(polygon) != self.POLYGON:
                print "not a polygon", polygon.GetName()
                return
        if vertices != None:
            [polygon.SetPoint(k, self.FromVec(v)) for k, v in enumerate(vertices)]
        #            for k,v in enumerate(vertices) :
        #                polygon.SetPoint(k, self.FromVec(v))
        if faces != None:
            [polygon.SetPolygon(k, self.FromFace(f)) for k, f in enumerate(faces)]
        polygon.Message(c4d.MSG_UPDATE)
        c4d.EventAdd()
        # should we send other message?

    #        self.update()

    def redoPoly(self, poly, vertices, faces, proxyCol=False, colors=None, parent=None, mol=None):
        doc = self.getCurrentScene()
        doc.SetActiveObject(poly)
        name = poly.GetName()
        texture = poly.GetTags()[0]
        c4d.CallCommand(100004787)  # delete the obj
        obj = self.createsNmesh(name, vertices, None, faces, smooth=False, material=texture[1010], proxyCol=proxyCol)
        self.addObjectToScene(doc, obj[0], parent=parent)
        if proxyCol and colors != None:
            pObject = self.getObject(name + "_color")
            doc.SetActiveObject(pObject)
            c4d.CallCommand(100004787)  # delete the obj
            pObject = PolygonColorsObject(name, colors)
            self.addObjectToScene(doc, pObject, parent=parent)

    def reCreatePoly(self, poly, vertices, faces, proxyCol=False, colors=None, parent=None, mol=None):
        doc = self.getCurrentScene()
        doc.SetActiveObject(poly)
        name = poly.GetName()
        texture = poly.GetTags()[0]
        c4d.CallCommand(100004787)  # delete the obj
        obj = self.createsNmesh(name, vertices, None, faces, smooth=False, material=texture[1010], proxyCol=proxyCol)
        self.addObjectToScene(doc, obj[0], parent=parent)
        if proxyCol and colors != None:
            pObject = self.getObject(name + "_color")
            doc.SetActiveObject(pObject)
            c4d.CallCommand(100004787)  # delete the obj
            pObject = self.PolygonColorsObject(name, colors)
            self.addObjectToScene(doc, pObject, parent=parent)

    """def UVWColorTag(obj,vertColors):
          uvw=obj.MakeTag(c4d.Tuvw)

          obj= c4d.PolygonObject(len(vertColors), len(vertColors)/2.)
          obj.SetName(name+'_color')
          k=0
          for v in vertColors :
              print v
              obj.SetPoint(k, c4d.Vector(float(v[0]), float(v[1]), float(v[2])))
              k=k+1
          return obj
    """

    def updateMesh(self, o, vertices=None, faces=None, smooth=False, **kw):
        if type(o) == str:
            o = self.getObject(o)
        if o == None: return
        #        objdcache=obj.GetDeformCache()
        #        objcache=obj.GetCache()
        #        if objdcache is not None:
        #            obj = objdcache
        #        elif objcache is not None:
        #            obj = objcache
        oldN = o.GetPointCount()
        newN = len(vertices)
        if faces is not None:
            nF = len(faces)
        else:
            nF = 0
        o.ResizeObject(newN, nF)
        self.updatePoly(o, faces=faces, vertices=vertices)
        # sys.stderr.write('\nnb v %d %d f %d' % (oldN,len(vertices),len(faces)))

    def updateMeshProxy(self, obj, proxyCol=False, parent=None, mol=None):
        doc = getCurrentScene()
        doc.SetActiveObject(g.obj)
        name = obj.GetName()
        texture = obj.GetTags()[0]
        c4d.CallCommand(100004787)  # delete the obj
        vertices = g.getVertices()
        faces = g.getFaces()
        #        if DEBUG : print len(vertices),len(faces)
        sys.stderr.write('\nnb v %d f %d\n' % (len(vertices), len(faces)))
        # if     proxyCol : o=PolygonColorsObject
        obj = self.createsNmesh(name, vertices, None, faces, smooth=False, material=texture[1010], proxyCol=proxyCol)
        self.addObjectToScene(doc, obj[0], parent=parent)
        # obj.Message(c4d.MSG_UPDATE)
        return obj[0]

    #    if proxyCol :
    #        colors=mol.geomContainer.getGeomColor(g.name)
    #        if hasattr(g,'color_obj'):
    #            pObject=g.color_obj#getObject(name+"_color")
    #            doc.SetActiveObject(pObject)
    #            c4d.CallCommand(100004787) #delete the obj
    #        pObject=PolygonColorsObject(name,colors)
    #        g.color_obj=pObject
    #        addObjectToScene(doc,pObject,parent=parent)

    def c4df(self, face, g, polygon):
        A = int(face[0])
        B = int(face[1])
        if len(face) == 2:
            C = B
            D = B
            poly = c4d.CPolygon(A, B, C)
        elif len(face) == 3:
            C = int(face[2])
            D = C
            poly = c4d.CPolygon(A, B, C)
        elif len(face) == 4:
            C = int(face[2])
            D = int(face[3])
            poly = c4d.CPolygon(A, B, C, D)
        polygon.SetPolygon(id=g, polygon=poly)
        return [A, B, C, D]

    def polygons(self, name, proxyCol=False, smooth=False, color=None, material=None, **kw):
        import time
        t1 = time.time()
        vertices = kw["vertices"]
        faces = kw["faces"]
        #        if faces is not None :
        #            faces = self.triangulateFaceArray(faces)
        normals = kw["normals"]
        frontPolyMode = 'fill'
        if kw.has_key("frontPolyMode"):
            frontPolyMode = kw["frontPolyMode"]
        if kw.has_key("shading"):
            shading = kw["shading"]  # 'flat'
        #          if frontPolyMode == "line" : #wire mode
        #              material = self.getCurrentScene().SearchMaterial("wire")
        #              if material == None:
        #                  material = self.addMaterial("wire",(0.5,0.5,0.5))
        polygon = c4d.PolygonObject(len(vertices), len(faces))
        polygon.SetName(name)
        k = 0

        [polygon.SetPoint(k, self.FromVec(v)) for k, v in enumerate(vertices)]
        [polygon.SetPolygon(k, self.FromFace(f)) for k, f in enumerate(faces)]

        t2 = time.time()
        polygon.MakeTag(c4d.Tphong)  # shading ?
        # create a texture tag on the PDBgeometry object
        doMaterial = True
        if type(material) is bool or not proxyCol:
            doMaterial = material
        elif material is None:
            doMaterial = False
        if not proxyCol:  # and doMaterial:
            if material != None:
                texture = polygon.MakeTag(c4d.Ttexture)
                texture[1010] = material
            #                texture[1010] = self.addMaterial("mat_"+name,color[0])
            #            else : texture[1010] = material
            #          else :
        # need to test with autoPack
        if material is None and color is not None and len(color) == 1:
            texture = polygon.MakeTag(c4d.Ttexture)
            texture[1010] = self.addMaterial("mat_" + name, color[0])
        #                self.changeColor(polygon,color,proxyObject=True)
        polygon.Message(c4d.MSG_UPDATE)
        return polygon

    def createsNmesh(self, name, vertices, vnormals, faces, smooth=False,
                     material=None, proxyCol=False, color=None, **kw):
        """
        This is the main function that create a polygonal mesh.

        @type  name: string
        @param name: name of the pointCloud
        @type  vertices: array
        @param vertices: list of x,y,z vertices points
        @type  vnormals: array
        @param vnormals: list of x,y,z vertex normals vector
        @type  faces: array
        @param faces: list of i,j,k indice of vertex by face
        @type  smooth: boolean
        @param smooth: smooth the mesh
        @type  material: hostApp obj
        @param material: material to apply to the mesh
        @type  proxyCol: booelan
        @param proxyCol: do we need a special object for color by vertex (ie C4D)
        @type  color: array
        @param color: r,g,b value to color the mesh, [[1,0,0],]

        @rtype:   hostApp obj
        @return:  the polygon object
        """
        if color is not None and len(color) == 3:
            if type(color[0]) is not list:
                color = [color, ]
        PDBgeometry = self.polygons(name, vertices=vertices, normals=vnormals,
                                    faces=faces, material=material, color=color,
                                    smooth=smooth, proxyCol=proxyCol)
        parent = None
        if "parent" in kw:
            parent = kw["parent"]
        self.addObjectToScene(None, PDBgeometry, parent=parent)
        return [PDBgeometry, PDBgeometry]

    def instancePolygon(self, name, matrices=None, hmatrices=None, mesh=None, parent=None,
                        transpose=False, globalT=True, dupliVert=True, **kw):
        name = str(name)
        if hmatrices is not None:
            matrices = hmatrices
        if matrices == None: return None
        if mesh == None: return None
        instance = []
        #        self.dupliVert = False
        if self.instance_dupliFace:
            v = [0., 1., 0.]
            if "axis" in kw and kw["axis"] is not None:
                v = kw["axis"]
            print ("axis", v)
            o = self.getObject(name + "ds")
            if o is None:
                o, m = self.matrixToFacesMesh(name, matrices, vector=v, transpose=transpose,
                                              parent=parent)
                # create cloner Object
                cloner = c4d.BaseObject(self.CLONER)
                cloner[c4d.ID_BASELIST_NAME] = name + "ds"
                cloner[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0  # object
                self.addObjectToScene(None, cloner, parent=parent)
                cloner[c4d.MG_OBJECT_LINK] = o
                cloner[c4d.MG_POLY_MODE_] = 2  # Face is 2
                # self._render_instance
                if hasattr(c4d,"MGCLONER_VOLUMEINSTANCES") :
                    cloner[c4d.MGCLONER_VOLUMEINSTANCES] = int(self._render_instance)
                else :
                    cloner[c4d.MGCLONER_VOLUMEINSTANCES_MODE] = 2 #multi-instqnce?
                #                cloner[c4d.MG_POLY_UPVECTOR]=self.getTrackAxis(v)
                self.reParent(mesh, cloner)
                instance = [o]
            else:
                v, f, rnorm = self.matrixToFaces(name, matrices, vector=vector, transpose=transpose, **kw)
                self.updatePoly(o, faces=f, vertices=v)
            return o
            # rotation checkbox->use normal
        elif self.dupliVert:
            v = [0., 1., 0.]
            if "axis" in kw:
                v = kw["axis"]
            print ("axis", v)
            o = self.getObject(name)
            if o is None:
                o, m = self.matrixToEdgeMesh(name, matrices, vector=v)
                cloner = c4d.BaseObject(self.CLONER)
                cloner[c4d.ID_BASELIST_NAME] = name + "ds"
                cloner[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0  # object
                self.addObjectToScene(None, cloner, parent=parent)
                cloner[c4d.MG_OBJECT_LINK] = o
                cloner[c4d.MG_POLY_MODE_] = 0  # edgis is 1
                cloner[c4d.MG_POLY_UPVECTOR] = self.getTrackAxis(v)
                if parent is not None:
                    self.reParent(mesh, cloner)
            else:
                # update
                pass
                # rotation checkbox->use normal
        else:
            # print len(matrices)#4,4 mats
            for i, mat in enumerate(matrices):
                inst = self.getObject(name + str(i))
                if inst is None:
                    inst = c4d.BaseObject(c4d.Oinstance)
                    inst.SetName(name + str(i))
                    self.AddObject(inst, parent=parent)
                instance.append(inst)
                instance[-1][1001] = mesh
                if hmatrices is not None:
                    mx = mat
                elif matrices is not None:
                    if type(mat) != c4d.Matrix:
                        mx = self.matrix2c4dMat(mat, transpose=transpose)
                    else:
                        mx = mat
                if globalT:
                    instance[-1].SetMg(mx)  # scaling ?
                else:
                    instance[-1].SetMl(mx)
                    # instance[-1].MakeTag(c4d.Ttexture)
        return instance

    def updateInstancePolygon(self, name, instance, matrices=None, hmatrices=None, mesh=None,
                              parent=None, transpose=False, globalT=True):
        name = str(name)
        if matrices == None: return None
        if mesh == None: return None
        # instance = []
        # print len(matrices)#4,4 mats
        if instance is None:
            instance = []
        if hmatrices is not None:
            matrices = hmatrices
        if self.instance_dupliFace:
            o = self.getObject(name + "_me")
            v, f, rnorm = self.matrixToFaces(name, matrices, vector=vector, transpose=transpose, **kw)
            self.updatePoly(o, faces=f, vertices=v)
            if rnorm == True:
                # select it
                self.setCurrentSelection([o])
                c4d.CallCommand(self.REVERSE_NORMAL)
                polygon.Message(c4d.MSG_UPDATE)
                c4d.EventAdd()
        elif self.dupliVert:
            pass
        else:
            for i, mat in enumerate(matrices):
                inst = self.getObject(name + str(i))
                if i > len(instance) or inst is None:
                    inst = c4d.BaseObject(c4d.Oinstance)
                    inst.SetName(name + str(i))
                    self.AddObject(inst, parent=parent)
                    instance.append(inst)
                inst[1001] = mesh
                if hmatrices is not None:
                    mx = mat
                elif matrices is not None:
                    mx = self.matrix2c4dMat(mat, transpose=transpose)
                if globalT:
                    inst.SetMg(mx)
                else:
                    inst.SetMl(mx)
                    # instance[-1].MakeTag(c4d.Ttexture)
        return instance

    def setVColor(self, j, ncolor):
        _colsc = 1.0
        if ncolor is None:
            return 0.
        if (j == 0): return ncolor.x / _colsc
        if (j == 1): return ncolor.y / _colsc
        if (j == 2): return ncolor.z / _colsc

    def CreateVertexRGBmaps(self, mesh, proxy=None, vcolors=None):

        pcnt = mesh.GetPointCount()
        unic = False
        useProxy = True
        createV = True
        createM = True
        colsc = 1.0

        if vcolors is None:
            vcolors = [c4d.Vector(0., 0., 0.), ] * pcnt
            unic = True
        else:
            # print "vcolors", len(vcolors)
            if len(vcolors) == 1:
                unic = True
        useProxy = False

        if mesh.GetTag(c4d.Ttexture) != None:
            createM = False

        for j in range(3):
            createV = True
            vFirstTag = mesh.GetFirstTag()
            vLastTag = None;
            if (j == 0): vColor = "_Red"
            if (j == 1): vColor = "_Green"
            if (j == 2): vColor = "_Blue"
            tagName = vColor  # MoleculeName +

            while (vFirstTag is not None):
                vLastTag = vFirstTag
                if vLastTag.GetName() == tagName:
                    createV = False
                    vtag = vLastTag
                    break
                vFirstTag = vFirstTag.GetNext()
            if createV:
                vtag = mesh.MakeVariableTag(c4d.Tvertexmap, pcnt, vLastTag)
                vtag.SetName(tagName)
            if vtag is None:
                return False

            mesh.Message(c4d.MSG_UPDATE)
            # get the vertex map tag's size (should be same as vertex (point) count
            vcnt = vtag.GetDataCount()
            # get the pointer to the vertex map array
            vmap = vtag.GetAllHighlevelData()
            vmap = [self.setVColor(j, y) for y in vcolors]
            #            vmap=map(lambda x,y,j=j: setVColor(x,j,y),vmap,vcolors)
            vtag.SetAllHighlevelData(vmap)
            vtag.Message(c4d.MSG_UPDATE)
            c4d.EventAdd()
            if createM:
                MatMemb = self.CreateVertexColorMaterials(0, mesh, vtag)
                MatTag = c4d.TextureTag()
                if (MatTag):
                    MatTag.SetMaterial(MatMemb)
                    if j != 0:
                        MatTag[c4d.TEXTURETAG_MIX] = 1
                    mesh.InsertTag(MatTag, vLastTag)

    def CreateVertexColorMaterials(self, ID_MEMBMAT, pPolyObject, vtag):
        vColor = vtag.GetName()
        Mat = c4d.BaseMaterial(c4d.Mmaterial)
        Mat.SetName(vColor)

        Mat[c4d.MATERIAL_COLOR_COLOR] = c4d.Vector(0.902, 0.730, 0.659)
        #    MatMemb->SetParameter(MATERIAL_COLOR_COLOR, Vector(0.902, 0.730,0.659), NULL);
        #    MatMemb->SetParameter(MATERIAL_USE_TRANSPARENCY, 1, NULL);
        #    MatMemb->SetParameter(MATERIAL_USE_BUMP, 1, NULL);
        #    MatMemb->SetParameter(MATERIAL_BUMP_STRENGTH, 0.25, NULL);
        Mat[c4d.MATERIAL_TRANSPARENCY_BRIGHTNESS] = 0.2
        Mat[c4d.MATERIAL_SPECULAR_WIDTH] = 0.29
        #    MatMemb->SetParameter(MATERIAL_SPECULAR_HEIGHT, 0.65, NULL);
        data = Mat.GetDataInstance()

        col = c4d.BaseList2D(c4d.Xfusion)
        blend = c4d.BaseList2D(c4d.Xcolor)

        blenddata = blend.GetDataInstance()
        # Set here your texture path, relative or absolute doesn't matter
        if vColor == "_Red":
            blenddata.SetData(c4d.COLORSHADER_COLOR, c4d.Vector(1, 0, 0))
        if vColor == "_Green":
            blenddata.SetData(c4d.COLORSHADER_COLOR, c4d.Vector(0, 1, 0))
        if vColor == "_Blue":
            blenddata.SetData(c4d.COLORSHADER_COLOR, c4d.Vector(0, 0, 1))
        blend.Message(c4d.MSG_UPDATE)
        Mat.InsertShader(blend)

        mask = c4d.BaseList2D(c4d.Xvertexmap)
        base = c4d.BaseList2D(c4d.Xcolor)

        maskdata = mask.GetDataInstance()
        objParent = pPolyObject
        objTag = vtag
        maskdata.SetLink(c4d.SLA_DIRTY_VMAP_OBJECT, objTag)
        mask.Message(c4d.MSG_UPDATE)
        data.SetLink(c4d.MATERIAL_BUMP_SHADER, mask)
        Mat.InsertShader(mask)
        basedata = base.GetDataInstance()
        basedata.SetData(c4d.COLORSHADER_COLOR, c4d.Vector(0, 0, 0))
        base.Message(c4d.MSG_UPDATE)
        Mat.InsertShader(base)

        coldata = col.GetDataInstance()
        # Set here your texture path, relative or absolute doesn't matter
        coldata.SetData(c4d.SLA_FUSION_USE_MASK, 1)
        coldata.SetLink(c4d.SLA_FUSION_BLEND_CHANNEL, blend)
        coldata.SetLink(c4d.SLA_FUSION_MASK_CHANNEL, mask)
        coldata.SetLink(c4d.SLA_FUSION_BASE_CHANNEL, base)
        col.Message(c4d.MSG_UPDATE)
        data.SetLink(c4d.MATERIAL_COLOR_SHADER, col)
        Mat.InsertShader(col)

        Mat.Message(c4d.MSG_UPDATE)
        Mat.Update(True, True)
        c4d.EventAdd()

        doc = c4d.documents.GetActiveDocument()
        doc.InsertMaterial(Mat)
        doc.AddUndo(c4d.UNDO_NEW, Mat)
        return Mat

    def colorbyvertex(self, mesh, proxy=None, vcolors=None):
        if mesh.GetTag(c4d.Tphong) == None:
            mesh.MakeTag(c4d.Tphong)
        if mesh.GetTag(c4d.Tbaketexture) == None:
            vBakeTexTag = mesh.MakeTag(c4d.Tbaketexture)
            vBakeTexTag[c4d.BAKETEXTURE_CHANNEL_COLOR] = 0
            vBakeTexTag[c4d.BAKETEXTURE_CHANNEL_S_COLOR] = 1
            vBakeTexTag[c4d.BAKETEXTURE_MAPPING] = c4d.BAKETEXTURE_MAPPING_CUBIC
            vBakeTexTag[c4d.BAKETEXTURE_PIXELBORDER] = 3
            vBakeTexTag[c4d.BAKETEXTURE_BACKGROUND] = c4d.Vector(0.6, 1.0, 0.0)
            vBakeTexTag[c4d.BAKETEXTURE_RELAXCOUNT] = 2
            vBakeTexTag.Message(c4d.MSG_UPDATE)
            c4d.EventAdd()
        tags = mesh.GetTags()
        ntexture = 0
        for tag in tags:
            if type(tag) == c4d.TextureTag:
                ntexture += 1
        if ntexture < 3:
            while mesh.GetTag(c4d.Ttexture) != None:
                mesh.KillTag(c4d.Ttexture)
        self.CreateVertexRGBmaps(mesh, proxy, vcolors)
        doc = c4d.documents.GetActiveDocument()
        doc.AddUndo(c4d.UNDO_NEW, mesh)

    def colorMaterial(self, mat, col):
        # mat input is a material name or a material object
        # color input is three rgb value array
        if col == None:
            return
        doc = c4d.documents.GetActiveDocument()
        if type(mat) == str:
            material = doc.SearchMaterial(mat)
            if material is None:
                material = self.addMaterial(mat, col)
            mat = material
        mat[2100] = c4d.Vector(col[0], col[1], col[2])

    def c4dColor(self, col):
        # c4d color rgb range[0-1]
        if max(col) > 1.0:
            col = [(x / 255.) for x in col]
        #                col = map( lambda x: x/255., col)
        return col

    def changeColor(self, obj, colors, perVertex=False, proxyObject=True, doc=None, pb=False,
                    facesSelection=None, faceMaterial=False):
        #        print colors
        if colors is None:
            return
        if colors[0] is not list and len(colors) == 3:
            colors = [colors, ]
        #        print colors
        doc = self.getCurrentScene()
        if type(obj) == str:
            obj = self.getMesh(obj)
        print ("COLORING...", obj, self.getName(obj), self.getType(obj), self.getType(obj) != self.POLYGON, proxyObject)
        if self.getType(obj) != self.POLYGON:
            proxyObject = False
        defaultColor = (0.25, 0.25, 0.25)
        doProxy = False
        # verfify perVertex flag
        unic = False
        ncolor = self.convertColor(colors[0], toint=False)
        if len(colors) == 1:
            unic = True
            ncolor = self.convertColor(colors[0], toint=False)
        proxy = None
        vcolor = None
        # lets not doing it for see
        if proxyObject:
            nf = obj.GetPolygonCount()
            nv = obj.GetPointCount()
            mfaces = obj.GetAllPolygons()
            if facesSelection is not None:
                if type(facesSelection) is bool:
                    fsel, face_sel_indice = self.getMeshFace(obj, selected=True)
                else:
                    face_sel_indice = facesSelection
                    fsel = []
                    for i in face_sel_indice:
                        fsel.append(mfaces[i])
                vsel = []
                for f in fsel:
                    for v in f:
                        if v not in vsel:
                            vsel.append(v)
                mfaces = fsel
                nf = len(fsel)
                nv = len(vsel)
            if len(colors) != nv and \
                            len(colors) == nf:
                perVertex = False
            if len(colors) == nv and \
                            len(colors) != nf:
                perVertex = True
            # get the list of color in c4d format
            vcolor = [c4d.Vector(0.25, 0.25, 0.25)] * obj.GetPointCount()  # default color is grey
            # if DEBUG :
            # print "nb Faces ",len(faces)
            if pb:
                self.resetProgressBar()
                self.progressBar(label="color per Vertex : convert Color to C4D")
            for i, g in enumerate(mfaces):  # faces
                if not unic and not perVertex:
                    ncolor = self.convertColor(colors[i], toint=False)
                elif unic:
                    ncolor = self.convertColor(colors[0], toint=False)
                for j in [g.a, g.b, g.c, g.d]:  # vertices
                    if not unic and perVertex:
                        ncolor = self.convertColor(colors[j], toint=False)
                    #                    print j,ncolor
                    vcolor[j] = c4d.Vector(float(ncolor[0]),
                                           float(ncolor[1]),
                                           float(ncolor[2]))
                if pb:
                    self.progressBar(progress=float(i) / float(len(faces)))
            if pb:
                self.progressBar(label="color per Vertex : create Vmap Tag")
            self.colorbyvertex(obj, proxy, vcolor)
            if pb:
                self.resetProgressBar()
        else:
            self.changeObjColorMat(obj, ncolor)
            texture = obj.GetTags()[0]  # should be the textureFlag

    def changeObjColorMat(self, obj, color):
        doc = self.getCurrentScene()
        #        texture = obj.GetTags()[0]
        texture = obj.GetTag(c4d.Ttexture)
        if texture is None:
            texture = obj.MakeTag(c4d.Ttexture)
        rMat = texture[c4d.TEXTURETAG_MATERIAL]
        if rMat is None:
            rMat = self.addMaterial("mat_" + self.getName(obj), color)
            texture[c4d.TEXTURETAG_MATERIAL] = rMat
        else:
            self.colorMaterial(rMat, color)

    def updateArmature(self, basename, x, listeName=None, scn=None, root=None, **kw):
        for j in range(len(x)):
            name = basename + 'bone' + str(j)
            if listeName is not None:
                name = listeName[j]
            bone = self.getObject(name)
            if bone is None:
                continue
            atC = x[j]
            mx = c4d.Matrix()
            mx.off = self.FromVec(atC)
            bone.SetMg(mx)

    def armature(self, basename, x, listeName=None, scn=None, root=None, **kw):
        bones = []
        #        mol = x[0].top
        center = [0, 0, 0]  # self.getCenter(x)
        #        if scn != None:
        parent = c4d.BaseObject(c4d.Onull)
        parent.SetName(basename)
        self.addObjectToScene(scn, parent, parent=root)
        for j in range(len(x)):
            name = basename + 'bone' + str(j)
            if listeName is not None:
                name = listeName[j]
            atC = x[j]
            bones.append(c4d.BaseObject(self.BONE))
            bones[j].SetName(name)
            relativePos = [0., 0., 0.]
            if j > 0:
                patC = x[j - 1]
                for i in range(3): relativePos[i] = (atC[i] - patC[i])
            else:  # the first atom
                # relative should be against the master
                #                center=Numeric.array(center)
                for i in range(3): relativePos[i] = (atC[i] - center[i])  # ??
            bones[j].SetAbsPos(self.FromVec(relativePos))
            mx = c4d.Matrix()
            mx.off = self.FromVec(atC)
            bones[j].SetMg(mx)
            #            if scn != None :
            if j == 0:
                self.addObjectToScene(scn, bones[j], parent=parent)
            else:
                self.addObjectToScene(scn, bones[j], parent=bones[j - 1])
        return parent, bones

    def bindGeom2Bones(self, listeObject, bones, delete=False):
        """
        Make a skinning. Namely bind the given bones to the given list of geometry.
        This function will joins the list of geomtry in one geometry

        @type  listeObjects: list
        @param listeObjects: list of object to joins
        @type  bones: list
        @param bones: list of joins
        """

        if len(listeObject) > 1:
            self.JoinsObjects(listeObject, delete=delete)
        else:
            self.ObjectsSelection(listeObject, "new")
        # 2- add the joins to the selection
        self.ObjectsSelection(bones, "add")
        # 3- bind the bones / geoms
        c4d.CallCommand(self.BIND)

    def updateMetaball(self, name, vertices=None):
        if vertices is None:
            return
        self.updatePoly(name + "_cloud", vertices=vertices)

    def metaballs(self, name, listePt, listeR, scn=None, root=None, **kw):
        doc = self.getCurrentScene()
        cloud = self.PointCloudObject(name + "_cloud",
                                      vertices=listePt,
                                      parent=root, atomarray=False)[0]
        metab = self.create_metaballs(name, sourceObj=cloud, parent=root)
        return metab, cloud

    def create_metaballs(self, name, sourceObj=None, source="", parent=None, coords=None):
        doc = self.getCurrentScene()
        metab = c4d.BaseObject(c4d.Ometaball)
        metab.SetName(name)
        metab[c4d.METABALLOBJECT_EXPONENTIAL] = 1
        metab[c4d.METABALLOBJECT_THRESHOLD] = 0.1  # Hull Value
        metab[c4d.METABALLOBJECT_SUBEDITOR] = 2
        metab[c4d.METABALLOBJECT_SUBRAY] = 2
        metab.MakeTag(c4d.Tphong)
        self.addObjectToScene(doc, metab, parent=parent)
        # radius ?
        # get the could from mol
        if source:
            if source == "clouds":
                cloud = self.getObject(name + "_cloud")
                if cloud is None:
                    cloud = self.PointCloudObject(name + "_cloud",
                                                  vertices=coords,
                                                  parent=metab, atomarray=False)[0]
                else:  # insertUnder Metaball Object
                    self.reParent(cloud, metab)
                # add the metaball Tag
                tag = cloud.MakeTag(c4d.Tmetaball)
                tag[c4d.METABALLTAG_RADIUS] = 1.0
                #            return metab
            elif sourceObj == "cpk":
                self.cpk_metaballs(name, coords, scn=doc, root=parent)
        elif sourceObj is not None:
            self.reParent(sourceObj, metab)
            tag = sourceObj.MakeTag(c4d.Tmetaball)
            tag[c4d.METABALLTAG_RADIUS] = 1.0
            # tag[c4d.METABALLTAG_STRENGTH]
        return metab

    def cpk_metaballs(self, name, atoms, scn=None, root=None):
        if scn == None:
            scn = self.getCurrentScene()
        parent = c4d.BaseObject(c4d.Onull)
        parent.SetName(name)
        self.addObjectToScene(scn, parent, parent=root)
        # mol = atoms[0].top
        # copy of the cpk ?-> point cloud is nice too...
        # create the metaball objects child of the null
        meta = c4d.BaseObject(self.METABALLS)
        self.addObjectToScene(scn, meta, parent=parent)
        # change the metaball parameter
        meta[1000] = 9.0  # Hull Value
        meta[1001] = 0.5  # editor subdivision
        meta[1002] = 0.5  # render subdivision
        # coloring ?
        return meta, parent

    def getBoxSize(self, obj):
        # take degree
        obj = self.getObject(obj)
        if obj is None:
            return
        return obj[1100]

    def box(self, name, center=[0., 0., 0.], size=[1., 1., 1.], cornerPoints=None, visible=1,
            mat=None, **kw):
        # import numpy
        box = c4d.BaseObject(c4d.Ocube)  # Object.New('Mesh',name)
        box.SetName(name)
        if cornerPoints != None:
            for i in range(3):
                size[i] = cornerPoints[1][i] - cornerPoints[0][i]
            for i in range(3):
                center[i] = (cornerPoints[0][i] + cornerPoints[1][i]) / 2.
        box.SetAbsPos(self.FromVec(center))
        box[1100] = self.FromVec(size)
        # aMat=addMaterial("wire")
        texture = box.MakeTag(c4d.Ttexture)
        if mat == None:
            texture[1010] = self.addMaterial("cube", [1., 1., 0.])
        else:
            texture[1010] = mat
        parent = None
        if "parent" in kw:
            parent = kw["parent"]
        self.addObjectToScene(self.getCurrentScene(), box, parent=parent)
        box[c4d.ID_BASEOBJECT_XRAY] = bool(visible)
        return box, box

    def updateBox(self, box, center=[0., 0., 0.], size=[1., 1., 1.], cornerPoints=None, visible=1,
                  mat=None):
        # import numpy
        box = self.getObject(box)
        if cornerPoints != None:
            for i in range(3):
                size[i] = cornerPoints[1][i] - cornerPoints[0][i]
            for i in range(3):
                center[i] = (cornerPoints[0][i] + cornerPoints[1][i]) / 2.
        box.SetAbsPos(self.FromVec(center))
        box[1100] = self.FromVec(size)
        # aMat=addMaterial("wire")

    #        texture = box.MakeTag(c4d.Ttexture)
    #        if mat == None:
    #            texture[1010] = self.addMaterial("cube",[1.,1.,0.])
    #        else :
    #            texture[1010] = mat
    #        self.addObjectToScene(self.getCurrentScene(),box)
    #        return box

    #    def getCornerPointCube(self,obj):
    #        size = obj[1100]
    #        center = obj.GetAbsPos()
    #        cornerPoints=[]
    #        #lowCorner
    #        lc = [center.x - size.x/2.,
    #              center.y - size.y/2.,
    #              center.z - size.z/2.]
    #        uc = [center.x + size.x/2.,
    #              center.y + size.y/2.,
    #              center.z + size.z/2.]
    #        cornerPoints=[[lc[2],lc[1],lc[0]],[uc[2],uc[1],uc[0]]]
    #        return cornerPoints

    def plane(self, name, center=[0., 0., 0.], size=[1., 1.], cornerPoints=None, visible=1, **kw):
        # import numpy
        plane = c4d.BaseObject(c4d.Oplane)  # Object.New('Mesh',name)
        plane.SetName(name)
        if cornerPoints != None:
            for i in range(3):
                size[i] = cornerPoints[1][i] - cornerPoints[0][i]
            for i in range(3):
                center[i] = (cornerPoints[0][i] + cornerPoints[1][i]) / 2.
        plane.SetAbsPos(self.FromVec(center))

        plane[c4d.PRIM_PLANE_WIDTH] = size[0]
        plane[c4d.PRIM_PLANE_HEIGHT] = size[1]

        if "subdivision" in kw:
            plane[c4d.PRIM_PLANE_SUBW] = kw["subdivision"][0]
            plane[c4d.PRIM_PLANE_SUBH] = kw["subdivision"][1]

        if "axis" in kw:  # orientation
            dic = {"+X": 0, "-X": 1, "+Y": 2, "-Y": 3, "+Z": 4, "-Z": 5}
            if type(kw["axis"]) is str:
                axis = dic[kw["axis"]]
            else:
                axis = kw["axis"]
            plane[c4d.PRIM_AXIS] = axis
        else:
            plane[c4d.PRIM_AXIS] = 1
        if "material" in kw:
            texture = plane.MakeTag(c4d.Ttexture)
            if type(kw["material"]) is c4d.BaseMaterial:
                texture[1010] = kw["material"]
            else:
                texture[1010] = self.addMaterial("plane", [1., 1., 0.])
        parent = None
        if "parent" in kw:
            parent = kw["parent"]
        self.addObjectToScene(self.getCurrentScene(), plane, parent=parent)
        return plane, plane

    def Platonic(self, name, Type, radius, **kw):
        dicT = {"tetra": 0,
                "hexa": 1,
                "octa": 2,
                "dodeca": 3,
                "icosa": 4}  # BuckyBall ?
        dicTF = {4: 0,
                 6: 1,
                 8: 2,
                 12: 3,
                 20: 4}
        platonic = c4d.BaseObject(self.PLATONIC)
        platonic.SetName(name)
        if Type in dicT:
            platonic[c4d.PRIM_PLATONIC_TYPE] = dicT[Type]
        elif Type in dicTF:
            platonic[c4d.PRIM_PLATONIC_TYPE] = dicTF[Type]
        platonic[c4d.PRIM_PLATONIC_RAD] = radius
        parent = None
        if "parent" in kw:
            parent = kw["parent"]
        self.addObjectToScene(self.getCurrentScene(), platonic, parent=parent)
        if "material" in kw:
            texture = platonic.MakeTag(c4d.Ttexture)
            if type(kw["material"]) is c4d.BaseMaterial:
                texture[1010] = kw["material"]
            else:
                texture[1010] = self.addMaterial(name + "_mat", [1., 1., 0.])
        return platonic, platonic

    def alignNormal(self, poly):
        # select poly
        doc = self.getCurrentScene()
        doc.SetActiveObject(poly)
        c4d.CallCommand(14023)  # alignNormal

    def triangulate(self, poly):
        # select poly
        doc = self.getCurrentScene()
        doc.SetActiveObject(poly)
        c4d.CallCommand(14048)  # triangulate

    def makeEditable(self, object, copy=True):
        doc = self.getCurrentScene()
        # make a copy?
        if object is None:
            return
        if copy:
            clone = object.GetClone()
            clone.SetName(object.GetName() + "clone")
            doc.InsertObject(clone)
            doc.SetActiveObject(clone)
            c4d.CallCommand(12236)  # make editable can create a child
            clone.Message(c4d.MSG_UPDATE)
            clone = self.getObject(object.GetName() + "clone")
            print clone.GetType(), clone.GetType() == c4d.Oinstance
            if clone.GetType() != self.POLYGON:
                print "do editable"
                c4d.CallCommand(12236)  # make editable
                clone = self.getObject(object.GetName() + "clone")
            #            print clone
            return clone
        else:
            if object.GetType() != self.POLYGON:
                doc.SetActiveObject(object)
                c4d.CallCommand(12236)
                object.Message(c4d.MSG_UPDATE)
                #                object = self.getObject(object.GetName())
                if object.GetType() != self.POLYGON:
                    # should wedo it recursivey untilfindn a polygon?
                    # chec the child
                    ch = self.getChilds(object)
                    if len(ch) != 0:
                        object = ch[0]
                        if object.GetType() != self.POLYGON:
                            doc.SetActiveObject(object)
                            c4d.CallCommand(12236)  # make editable
                            object.Message(c4d.MSG_UPDATE)
                            #                            object = self.getObject(ch[0].GetName())
                            ch = self.getChilds(object)
                            if len(ch) != 0:
                                object = self.makeEditable(ch[0], copy=False)
            return object

    def getMeshVertices(self, poly, selected=False, **kw):
        if type(poly) == str:
            poly = self.getObject(poly)
        c4dvertices = poly.GetAllPoints()
        transform = False
        if "transform" in kw:
            transform = kw["transform"]
        mat = None
        if transform:
            mat = self.getTransformation(poly)
        if selected:
            sel = poly.GetPointS()
            nv = poly.GetPointCount()
            point_index = [i for i, e in enumerate(sel.GetAll(nv)) if e == 1]
            if transform:
                vertices = [self.ToVec(c4dvertices[v] * mat) for v in point_index]
            else:
                vertices = [self.ToVec(c4dvertices[v]) for v in point_index]
            return vertices, point_index
        else:
            if transform:
                vertices = [self.ToVec(v * mat) for v in c4dvertices]  # map(self.ToVec,c4dvertices)
            else:
                vertices = [self.ToVec(v) for v in c4dvertices]  # map(self.ToVec,c4dvertices)
            return vertices

    def getMeshNormales(self, poly, selected=False, **kw):
        c4dvnormals = poly.CreatePhongNormals()
        vnormals = vertices[:]
        for i, f in enumerate(faces):
            # one face : 4 vertices
            for k, j in enumerate(f):
                # print i,j,(i*4)+k
                vnormals[j] = self.ToVec(c4dvnormals[(i * 4) + k])
        return vnormals

    def getMeshEdge(self, c4dedge, **kw):
        return None  # [c4dedge.a,c4dedge.b]

    def getMeshEdges(self, poly, selected=False, **kw):
        return None

    #        c4dedges = object.GetEdge()
    #        faces = [self.getMeshEdge(e) for e in c4dedges]
    #        return faces

    def getFace(self, c4dface, r=True, **kw):
        if r:
            if c4dface.c == c4dface.d:
                return [c4dface.c, c4dface.b, c4dface.a]
            else:
                return [c4dface.d, c4dface.c, c4dface.b, c4dface.a]
        else:
            if c4dface.c == c4dface.d:
                return [c4dface.a, c4dface.b, c4dface.c]
            else:
                return [c4dface.a, c4dface.b, c4dface.c, c4dface.d]

    def getFaces(self, object, selected=False, **kw):
        print object, object.GetName()
        c4dfaces = object.GetAllPolygons()
        if selected:
            nf = object.GetPolygonCount()
            sel = object.GetPolygonS()
            c4dfaces_index = [i for i, e in enumerate(sel.GetAll(nf)) if e == 1]  # only want wen val = 1
            faces = [self.getFace(c4dfaces[f]) for f in c4dfaces_index]
            return faces, c4dfaces_index
        else:
            c4dfaces = object.GetAllPolygons()
            faces = [self.getFace(f) for f in c4dfaces]
            return faces

    def getMeshFaces(self, poly, selected=False, **kw):
        return self.getFaces(poly, selected=selected)


        #################################################################################

    #    def setupAmber(mv,name,mol,prmtopfile, type,add_Conf=True,debug = False):
    #        if not hasattr(mv,'setup_Amber94'):
    #            mv.browseCommands('amberCommands', package='Pmv')
    #        from Pmv import amberCommands
    #        amberCommands.Amber94Config = {}
    #        amberCommands.CurrentAmber94 = {}
    #
    #        mv.energy = C.EnergyHandler(mv)
    #        mv.energy.amber = True
    #        mv.energy.mol = mol
    #        mol.prname = prmtopfile
    #        mv.energy.name=name
    #        def doit():
    #            c1 = mv.minimize_Amber94
    #            c1(name, dfpred=10.0, callback_freq='10', callback=1, drms=1e-06, maxIter=10, log=0)
    #        mv.energy.doit=doit
    #        if add_Conf:
    #                confNum = 1
    #                # check number of conformations available
    #                current_confNum = len(mol.allAtoms[0]._coords) -1
    #                if  current_confNum < confNum:
    #                    # we need to add conformation
    #                    for i in range((confNum - current_confNum)):
    #                        mol.allAtoms.addConformation(mol.allAtoms.coords)
    #                        # uses the conformation to store the transformed data
    #                        #mol.allAtoms.updateCoords(vt,ind=confNum)
    #                        # add arconformationIndex to top instance ( molecule)
    #                        mol.cconformationIndex = confNum
    #        mv.setup_Amber94(mol.name+":",name,prmtopfile,indice=mol.cconformationIndex)
    #        mv.minimize_Amber94(name, dfpred=10.0, callback_freq='10', callback=1, drms=1e-06, maxIter=100., log=0)
    #
    #    def cAD3Energies(mv,mols,atomset1,atomset2,add_Conf=False,debug = False):
    #        mv.energy = C.EnergyHandler(mv)
    #        mv.energy.add(atomset1,atomset2)#type=c_ad3Score by default
    #        #mv.energy.add(atomset1,atomset2,type = "ad4Score")
    #        if add_Conf:
    #            confNum = 1
    #            for mol in mols:
    #                # check number of conformations available
    #                current_confNum = len(mol.allAtoms[0]._coords) -1
    #                #if  current_confNum < confNum:
    #                # we need to add conformation
    #                #for i in range((confNum - current_confNum)):
    #                mol.allAtoms.addConformation(mol.allAtoms.coords)
    #                        # uses the conformation to store the transformed data
    #                        #mol.allAtoms.updateCoords(vt,ind=confNum)
    #                        # add arconformationIndex to top instance ( molecule)
    #                mol.cconformationIndex = len(mol.allAtoms[0]._coords) -1
    #        if debug :
    #            s1=c4d.BaseObject(c4d.Osphere)
    #            s1.SetName("sphere_rec")
    #            s1[PRIM_SPHERE_RAD]=2.
    #            s2=c4d.BaseObject(c4d.Osphere)
    #            s2.SetName("sphere_lig")
    #            s2[PRIM_SPHERE_RAD]=2.
    #            addObjectToScene(getCurrentScene(),s1)
    #            addObjectToScene(getCurrentScene(),s2)
    #            #label
    #            label = newEmpty("label")
    #            label.MakeTag(LOOKATCAM)
    #            addObjectToScene(getCurrentScene(),label)
    #            text1 =  c4d.BaseObject(TEXT)
    #            text1.SetName("score")
    #            text1[2111] = "score : 0.00"
    #            text1[2115] = 5.
    #            text1[904,1000] = 3.14
    #            text1[903,1001] = 4.
    #            text2 =  c4d.BaseObject(TEXT)
    #            text2.SetName("el")
    #            text2[2111] = "el : 0.00"
    #            text2[2115] = 5.0
    #            text2[904,1000] = 3.14
    #            text3 =  c4d.BaseObject(TEXT)
    #            text3.SetName("hb")
    #            text3[2111] = "hb : 0.00"
    #            text3[2115] = 5.0
    #            text3[904,1000] = 3.14
    #            text3[903,1001] = -4.
    #            text4 =  c4d.BaseObject(TEXT)
    #            text4.SetName("vw")
    #            text4[2111] = "vw : 0.00"
    #            text4[2115] = 5.0
    #            text4[904,1000] = 3.14
    #            text4[903,1001] = -8.
    #            text5 =  c4d.BaseObject(TEXT)
    #            text5.SetName("so")
    #            text5[2111] = "so : 0.00"
    #            text5[2115] = 5.0
    #            text5[904,1000] = 3.14
    #            text5[903,1001] = -12.
    #            addObjectToScene(getCurrentScene(),text1,parent=label)
    #            addObjectToScene(getCurrentScene(),text2,parent=label)
    #            addObjectToScene(getCurrentScene(),text3,parent=label)
    #            addObjectToScene(getCurrentScene(),text4,parent=label)
    #            addObjectToScene(getCurrentScene(),text5,parent=label)
    #        #return energy
    #
    #    def changeColorO(self,object,colors):
    #        object.GetTags()[0][1010][2100]= c4d.Vector( colors[0],colors[1],colors[2])
    #
    #    def colorByEnergy(vf,atomSet,scorer,property):
    #        mini = min(getattr(atomSet,scorer.prop))
    #        #geomsToColor = vf.getAvailableGeoms(scorer.mol2)
    #        vf.colorByProperty(atomSet,['cpk'],property,
    #                                mini=-1.0, maxi=1.0,
    #                                colormap='rgb256',log=1)#,
    #    #                            createEvents=False)
    #        #then i should manually apply all the color on sph
    #    #    mol = atomSet[0].getParentOfType(Protein)
    #    #    sph = mol.geomContainer.geoms['cpk'].obj
    #    #    #should change the material color for all sph.obj
    #    #    #map or new function ?
    #    ##    map( lambda x.foo, list)
    #    ##    by
    #    ##    [x.foo for x in list]
    #    #    #map(lambda x,y: x.GetTags()[0][1010][2100]= c4d.Vector( y.colors['cpk'][0],y.colors['cpk'][1],y.colors['cpk'][2]),sph,atomSet)
    #    #    #for i,atm in enumerate(atomSet):
    #    #    #    sph[i].GetTags()[0][1010][2100]= c4d.Vector( atm.colors['cpk'][0],atm.colors['cpk'][1],atm.colors['cpk'][2])
    #    #    [changeColorO(x,a.colors['cpk']) for x,a in zip(sph,atomSet)]
    #        #col = atomSet[0].colors['cpk']
    #        #mat = o.GetTags()[0][1010][2100] = c4d.Vector(col[0],col[1],col[2])
    #
    ##    def get_nrg_score(energy,display=True):
    #        #print "get_nrg_score"
    #        status = energy.compute_energies()
    #        print status
    #        if status is None: return
    #        #print energy.current_scorer
    #        print energy.current_scorer.score
    #        vf = energy.viewer
    #        if energy.label:
    #            text = getObject("score")
    #            if text != None :
    #                text[2111] = "score :"+str(energy.current_scorer.score)[0:5]
    #                for i,term in enumerate(['el','hb','vw','so']):
    #                    labelT = getObject(term)
    #                    labelT[2111] = term+" : "+str(energy.current_scorer.scores[i])[0:5]
    #        #should make multi label for multi terms
    #        # change color of ligand with using scorer energy
    #        if energy.color[0] or energy.color[1] :
    #            # change selection level to Atom
    #            prev_select_level = vf.getSelLev()
    #            vf.setSelectionLevel(Atom,log=0)
    #            scorer = energy.current_scorer
    #            property = scorer.prop
    #            if energy.color[0] :
    #                atomSet1 = vf.expandNodes(scorer.mol1.name).findType(Atom) # we pick the rec
    #                if hasattr(atomSet1,scorer.prop):
    #                    colorByEnergy(vf,atomSet1,scorer,property)
    #            if energy.color[1] :
    #                atomSet2 = vf.expandNodes(scorer.mol2.name).findType(Atom) # we pick the ligand
    #                if hasattr(atomSet2,scorer.prop):
    #                    colorByEnergy(vf,atomSet2,scorer,property)
    #                # get the geometries of colormap to be display
    #                #if vf.colorMaps.has_key('rgb256'):
    #                    #cmg = vf.colorMaps['rgb256']
    #                    #from DejaVu.ColormapGui import ColorMapGUI
    #                    #if not isinstance(cmg,ColorMapGUI):
    #                    #    cmg.read(self.colormap_file)
    #                    #    self.vf.showCMGUI(cmap=cmg, topCommand=0)
    #                    #    cmg = self.vf.colorMaps['rgb256']
    #                    #    cmg.master.withdraw()
    #                        # create the color map legend
    #                    #    cmg.createCML()
    #
    #                    #cml = cmg.legend
    #                    #cml.Set(visible=True,unitsString='kcal/mol')
    #                    #if cml not in self.geom_without_pattern:
    #                    #    self.geom_without_pattern.append(cml)
    #################################################################################

    #    def updateLigCoord(mol):
    #        #fake update...reset coord to origin
    #        mol.allAtoms.setConformation(0)
    #        #get the transformation
    #        name = mol.geomContainer.masterGeom.chains_obj[mol.chains[0].name]
    #        mx = getObject(name).get_ml()
    #        mat,imat = c4dMat2numpy(mx)
    #        vt = C.transformedCoordinatesWithMatrice(mol,mat)
    #        mol.allAtoms.updateCoords(vt,ind=mol.cconformationIndex)
    #        #coords = mol.allAtoms.coords
    #        #mol.allAtoms.updateCoords(coords,ind=mol.cconformationIndex)
    #        mol.allAtoms.setConformation(0)



    ##############################AR METHODS#######################################
    def ARstep(mv):
        # from Pmv.hostappInterface import comput_util as C
        mv.art.beforeRedraw()
        # up(self,dialog)
        for arcontext in mv.art.arcontext:
            for pat in arcontext.patterns.values():
                if pat.isdetected:
                    # print pat
                    geoms_2_display = pat.geoms
                    transfo_mat = pat.mat_transfo[:]
                    # print transfo_mat[12:15]
                    for geom in geoms_2_display:
                        if hasattr(pat, 'offset'):
                            offset = pat.offset[:]
                        else:
                            offset = [0., 0., 0.]
                        transfo_mat[12] = (transfo_mat[12] + offset[0]) * mv.art.scaleDevice
                        transfo_mat[13] = (transfo_mat[13] + offset[1]) * mv.art.scaleDevice
                        transfo_mat[14] = (transfo_mat[14] + offset[2]) * mv.art.scaleDevice
                        mat = transfo_mat.reshape(4, 4)
                        model = geom.obj
                        #                        print obj.GetName()
                        # r,t,s = C.Decompose4x4(Numeric.array(mat).reshape(16,))
                        # print t
                        # newPos = c4dv(t)
                        # model.SetAbsPos(newPos)
                        # model.Message(c4d.MSG_UPDATE)
                        setObjectMatrix(model, mat)
                        # updateAppli()

    def ARstepM(mv):
        # from Pmv.hostappInterface import comput_util as C
        from mglutil.math import rotax
        mv.art.beforeRedraw()
        # up(self,dialog)
        for arcontext in mv.art.arcontext:
            for pat in arcontext.patterns.values():
                if pat.isdetected:
                    # print pat
                    geoms_2_display = pat.geoms

                    # m = pat.mat_transfo[:]#pat.moveMat[:]
                    if mv.art.concat:
                        m = pat.moveMat[:].reshape(16, )
                    else:
                        m = pat.mat_transfo[:].reshape(16, )
                    # print transfo_mat[12:15]
                    for geom in geoms_2_display:
                        scale = float(mv.art.scaleObject)
                        model = geom.obj
                        if mv.art.patternMgr.mirror:
                            # apply scale transformation GL.glScalef(-1.,1.,1)
                            scaleObj(model, [-1., 1., 1.])
                        if mv.art.concat:
                            if hasattr(pat, 'offset'):
                                offset = pat.offset[:]
                            else:
                                offset = [0., 0., 0.]
                            m[12] = (m[12] + offset[0])  # * mv.art.scaleDevice
                            m[13] = (m[13] + offset[1])  # * mv.art.scaleDevice
                            m[14] = (m[14] + offset[2])  # * mv.art.scaleDevice
                            newMat = rotax.interpolate3DTransform([m.reshape(4, 4)], [1],
                                                                  mv.art.scaleDevice)
                            concatObjectMatrix(model, newMat)
                        else:
                            if hasattr(pat, 'offset'):
                                offset = pat.offset[:]
                            else:
                                offset = [0., 0., 0.]
                            m[12] = (m[12] + offset[0]) * mv.art.scaleDevice
                            m[13] = (m[13] + offset[1]) * mv.art.scaleDevice
                            m[14] = (m[14] + offset[2]) * mv.art.scaleDevice
                            # r1=m.reshape(4,4)
                            # newMat=rotax.interpolate3DTransform([r1], [1],
                            #                                mv.art.scaleDevice)
                            # m[0:3][0:3]=newMat[0:3][0:3]
                            setObjectMatrix(model, m.reshape(4, 4))
                        scaleObj(model, [scale, scale, scale])
                        # updateAppli()

    def ARloop(mv, ar=True, im=None, ims=None, max=1000):
        count = 0
        while count < max:
            # print count
            if im is not None:
                updateImage(mv, im, scale=ims)
            if ar:
                ARstep(mv)
            update()
            count = count + 1

    def AR(mv, v=None, ar=True):  # ,im=None,ims=None,max=1000):
        count = 0
        while 1:
            # print count
            if v is not None:
                # updateBmp(mv,bmp,scale=None,show=False,viewport=v)
                updateImage(mv, viewport=v)
            if ar:
                ARstepM(mv)
            # update()
            count = count + 1

    Y = range(480) * 640
    Y.sort()

    X = range(640) * 480

    # import StringIO
    # im = Image.open(StringIO.StringIO(buffer))
    # helper.updateImage(self,viewport=Right,order=[1, 2, 3, 1])
    def updateImage(mv, viewport=None, order=[1, 2, 3, 1]):
        # debug image is just white...
        try:
            if viewport is not None:
                viewport[c4d.BASEDRAW_DATA_SHOWPICTURE] = bool(mv.art.AR.show_tex)
            import Image
            cam = mv.art.arcontext[0].cam
            cam.lock.acquire()
            # print "acquire"
            # arcontext = mv.art.arcontext[0]
            # array = Numeric.array(cam.im_array[:])
            # n=int(len(array)/(cam.width*cam.height))
            if mv.art.AR.debug:
                array = cam.imd_array[:]  # .tostring()
                # print "debug",len(array)
            else:
                array = cam.im_array[:]  # .tostring()
                # print "normal",len(array)
            # img=Numeric.array(array[:])
            # n=int(len(img)/(arcontext.cam.width*arcontext.cam.height))
            # img=img.reshape(arcontext.cam.height,arcontext.cam.width,n)
            # if n == 3 :
            #    mode = "RGB"
            # else :
            #    mode = "RGBA"
            # im = Image.fromarray(img, mode)#.resize((160,120),Image.NEAREST).transpose(Image.FLIP_TOP_BOTTOM)
            im = Image.fromstring("RGBA", (mv.art.video.width, mv.art.video.height),
                                  array.tostring()).resize((320, 240), Image.NEAREST)
            # cam.lock.release()
            # scale/resize image ?
            # print "image"
            rgba = im.split()
            new = Image.merge("RGBA", (rgba[order[0]], rgba[order[1]], rgba[order[2]], rgba[order[3]]))
            # print "save"
            if mv.art.patternMgr.mirror:
                import ImageOps
                im = ImageOps.mirror(pilImage)
                imf = ImageOps.flip(im)
                imf.save("/tmp/arpmv.jpg")
            else:
                new.save("/tmp/arpmv.jpg")
            if viewport is not None:
                viewport[c4d.BASEDRAW_DATA_PICTURE] = "/tmp/arpmv.jpg"
            # print "update"
            cam.lock.release()
        except:
            print "PROBLEM VIDEO"

    def updateBmp(mv, bmp, scale=None, order=[3, 2, 2, 1], show=True, viewport=None):
        # cam.lock.acquire()
        # dialog.keyModel.Set(imarray=cam.im_array.copy())
        # cam.lock.release()
        # import Image
        cam = mv.art.arcontext[0].cam
        mv.art.arcontext[0].cam.lock.acquire()
        array = Numeric.array(cam.im_array[:])
        mv.art.arcontext[0].cam.lock.release()
        n = int(len(array) / (cam.width * cam.height))
        array.shape = (-1, 4)
        map(lambda x, y, v, bmp=bmp: bmp.SetPixel(x, y, v[1], v[2], v[3]), X, Y, array)

        if scale != None:
            bmp.Scale(scale, 256, False, False)
            if show: c4d.bitmaps.ShowBitmap(scale)
            scale.Save(name="/tmp/arpmv.jpg", format=c4d.symbols.FILTER_JPG)
        else:
            if show: c4d.bitmaps.ShowBitmap(bmp)
            bmp.Save(name="/tmp/arpmv.jpg", format=c4d.symbols.FILTER_JPG)
        if viewport is not None:
            viewport[c4d.symbols.BASEDRAW_DATA_PICTURE] = "/tmp/arpmv.jpg"

    from c4d import threading
    class c4dThread(threading.C4DThread):
        def __init__(self, func=None, arg=None):
            threading.C4DThread.__init__(self)
            self.func = func
            self.arg = arg

        def Main(self):
            self.func(self.arg)

    def render(self, name, w, h):
        doc = c4d.documents.GetActiveDocument()
        rd = doc.GetActiveRenderData().GetData()
        bmp = c4d.bitmaps.BaseBitmap()
        # Initialize the bitmap with the result size.
        # The resolution must match with the output size of the render settings.
        bmp.Init(x=w, y=h, depth=32)
        c4d.documents.RenderDocument(doc, rd, bmp, c4d.RENDERFLAGS_EXTERNAL)
        # bitmaps.ShowBitmap(bmp)
        bmp.Save(name, c4d.FILTER_TIF)

    # this should be in ePMV not in the helper
    def renderDynamic(epmv, traj, timeWidget=False, timeLapse=5):
        if timeWidget:
            dial = TimerDialog()
            dial.cutoff = 15.0
        if traj[0] is not None:
            if traj[1] == 'traj':
                mol = traj[0].player.mol
                maxi = len(traj[0].coords)
                mname = mol.name
                for i in range(maxi):
                    if timeWidget and (i % timeLapse) == 0:
                        dial.open()
                        if dial._cancel:
                            return False
                    traj[0].player.applyState(i)
                    updateDataGeom(epmv, mol)
                    update()
                    render("md%.4d" % i, 640, 480)

    # PARTICULE
    # this should be in a Tag, like redo all the particule at frame 0
    def getParticles(self, name, **kw):
        doc = self.getCurrentScene()
        PS = doc.GetParticleSystem()
        root = PS.GetRootGroup()
        if name is not None or name != "all":
            tpg = self.checkTPG(PS, name)
            return tpg
        if "group_name" in kw and kw["group_name"] is not None:
            # check if already exist
            tpg = self.checkTPG(PS, group_name)
            return tpg
        return PS

    def particle(self, name, coords, **kw):
        # default is all

        N = len(coords)
        doc = self.getCurrentScene()
        PS = doc.GetParticleSystem()
        root = PS.GetRootGroup()
        # if grp==None: grp = PS.GetRootGroup()
        # grp.GetParticles() return indice of all particle of this group
        # uid = PS.GetPData(i, channelid)
        ids = PS.AllocParticles(N)
        if "hostmatrice" in kw and kw["hostmatrice"] is not None:
            c4dC = [self.FromVec(c) * hostmatrice for c in coords]
        else:
            c4dC = map(self.FromVec, coords)
        map(PS.SetPosition, ids, c4dC)
        life = [c4d.BaseTime(360000.0)] * N
        map(PS.SetLife, ids, life)
        if "radius" in kw and kw["radius"] is not None:
            map(PS.SetSize, ids, radius)  # or vdwRadius?
        else:
            map(PS.SetSize, ids, [1.0] * N)  # or vdwRadius?
        map(PS.SetMass, ids, [1.0] * N)  # or atom mass?
        c4dV = map(self.FromVec, [(0., 0.0, 0.), ] * N)
        map(PS.SetVelocity, ids, c4dV)  # or atom mass?
        if name != "all" or ("group_name" in kw and kw["group_name"] is not None):
            # check if already exist
            group_name = name
            tpg = self.checkTPG(PS, group_name)
            if tpg is None:
                tpg = PS.AllocParticleGroup()
                PS.SetPGroupHierarchy(root, tpg, c4d.TP_INSERT_UNDERLAST)
                tpg[c4d.PGROUP_NAME] = group_name
            #            tpg.SetTitle(group_name)
            map(PS.SetGroup, ids, [tpg, ] * N)
            if "color" in kw and kw["color"] is not None:
                tpg[c4d.PGROUP_COLOR] = c4d.Vector(kw["color"][0], kw["color"][1], kw["color"][2])
            return tpg
        if "color" in kw and kw["color"] is not None:
            root[c4d.PGROUP_COLOR] = c4d.Vector(kw["color"][0], kw["color"][1], kw["color"][2])
        return PS

    def updateParticles(self, newPos, PS=None, **kw):
        # remove extra part lloc if need more
        group = None

        doc = self.getCurrentScene()
        GPS = doc.GetParticleSystem()
        if type(PS) == c4d.modules.thinkingparticles.TP_PGroup:
            group = PS
            PS = GPS

        #            doc = self.getCurrentScene()
        #            PS = doc.GetParticleSystem()
        Total = GPS.NumParticles()
        if group:
            currentN = group.NumParticles()
        else:
            currentN = PS.NumParticles()
        N = len(newPos)
        print("A ", currentN, N)
        ids = range(currentN)
        if group: ids = group.GetParticles()
        # reset life for current particle
        if group and Total < currentN:
            for i in range(Total, currentN):
                GPS.AllocParticle()
        if len(newPos) == 0:
            val = [-1, ] * len(ids)
            life = [c4d.BaseTime(-1)] * len(ids)
            map(PS.SetLife, ids, life)
            #            if group: GPS.FreeParticleGroup(group)
            #            else  : GPS.FreeAllParticles()
            return
        life = [c4d.BaseTime(360000.0)] * currentN
        map(PS.SetLife, ids, life)
        # need to create some and attach to group if any
        if N > currentN:
            for i in range(currentN, N):
                ids.append(GPS.AllocParticle())
                if group:
                    PS.SetGroup(ids[-1], group)
            cn = PS.NumParticles()
            if group: cn = group.NumParticles()
            life = [c4d.BaseTime(360000.0)] * cn
            map(PS.SetLife, range(cn), life)
        elif N < currentN:
            # removethe extra ne
            rids = range(N, currentN)
            val = [-1, ] * len(rids)
            #            map(PS.FreeParticle,rids)
            life = [c4d.BaseTime(-1)] * len(rids)
            map(PS.SetLife, rids, life)
        #            ids = range(PS.AllocParticle())#shuld be N
        c4dC = map(self.FromVec, newPos)
        ids = range(N)  # should bee <= to group.NumParticles()
        map(PS.SetPosition, ids, c4dC)

    def grid_particle(self, name, dimensions, origin, step, group_name=None,
                      radius=None, hostmatrice=None, **kw):
        # default is all
        NX, NY, NZ = dimensions
        N = dimensions[0] * dimensions[1] * dimensions[2]
        doc = self.getCurrentScene()
        PS = doc.GetParticleSystem()
        root = PS.GetRootGroup()
        # if grp==None: grp = PS.GetRootGroup()
        # grp.GetParticles() return indice of all particle of this group
        # uid = PS.GetPData(i, channelid)
        ids = PS.AllocParticles(N)
        #        indi, indj, indk = [range( N )]*3
        if hostmatrice is not None:
            c4dC = [
                self.FromVec([origin[0] + i * step[0], origin[1] + j * step[1], origin[2] + k * step[2]]) * hostmatrice
                for i, j, k in zip(indi, indj, indk)]
        else:
            for i in range(NX):
                for j in range(NY):
                    for k in range(NZ):
                        u = int(k * NX * NY + j * NX + i)
                        xyz = [origin[0] + i * step[0], origin[1] + j * step[1], origin[2] + k * step[2]]
                        c = self.FromVec(xyz)
                        PS.SetPosition(u, c)
                        PS.SetSize(u, 1.)
                        PS.SetMass(u, 1.)
                        PS.SetVelocity(u, self.FromVec([0., 0.0, 0.]))
        if group_name is not None:
            # check if already exist
            tpg = self.checkTPG(PS, group_name)
            if tpg is None:
                tpg = PS.AllocParticleGroup()
                PS.SetPGroupHierarchy(root, tpg, c4d.TP_INSERT_UNDERLAST)
                tpg[c4d.PGROUP_NAME] = group_name
            #            tpg.SetTitle(group_name)
            map(PS.SetGroup, ids, [tpg, ] * N)
            if color is not None:
                tpg[c4d.PGROUP_COLOR] = c4d.Vector(color[0], color[1], color[2])
            return tpg
        #        if color is not None :
        #            root[c4d.PGROUP_COLOR] = c4d.Vector(color[0],color[1],color[2])
        return PS

    def checkTPG(self, PS, group_name):
        groups = PS.GetParticleGroups()
        for g in groups:
            if g[c4d.PGROUP_NAME] == group_name:
                return g
        return None

    def createGroup(self, group_name, color=None, PS=None, parent=None):
        if PS is None:
            doc = self.getCurrentScene()
            PS = doc.GetParticleSystem()
        tpg = self.checkTPG(PS, group_name)
        if tpg is None:
            tpg = PS.AllocParticleGroup()
            tpg[c4d.PGROUP_NAME] = group_name
        if parent is None:
            parent = PS.GetRootGroup()
        PS.SetPGroupHierarchy(parent, tpg, c4d.TP_INSERT_UNDERLAST)
        if color is not None:
            tpg[c4d.PGROUP_COLOR] = c4d.Vector(color[0], color[1], color[2])
        return tpg

    def setParticlProperty(self, property, ids, values, PS=None):
        if PS == None:
            doc = self.getCurrentScene()
            PS = doc.GetParticleSystem()
        funct = {"group": PS.SetGroup,
                 "size": PS.SetSize,
                 "velocity": PS.SetVelocity,
                 "position": PS.SetPosition,
                 "life": PS.SetLife,
                 "age": PS.SetAge,
                 }
        map(funct[property], ids, values)

    def setParticulesPosition(self, newPos, PS=None):
        self.setParticlProperty("position", range(len(newPos)), newPos, PS=PS)

    def addDataChannel(self, PS, name, type="Real"):
        # type is
        PS.AddDataChannel(self.CH_DAT_TYPE[type], name)
        return PS.NumDataChannels() - 1

    def assignDataChannel(self, PS, channelid, listPID, listValue):
        uniq = False
        if len(listValue) == 1:
            uniq = True
        for i, id in enumerate(listPID):
            if uniq:
                val = listValue[0]
            else:
                val = listValue[i]
            PS.SetPData(id, channelid, val)

    def getDataChannel(self, PS, channelid, listPID):
        return [PS.GetData(id, channelid) for id in listPID]

        # ===============================================================================

    # specific C4D PARTICLE ie PyroCluster
    # ===============================================================================

    def newTPgeometry(self, name, group=None, material=None, pyro=False, parent=None):
        tpgeom = c4d.BaseObject(1001414)
        tpgeom.SetName(name)
        self.addObjectToScene(self.getCurrentScene(), tpgeom, parent=parent)
        if group is not None:
            tpgeom[c4d.PGEOM_LINK] = group
        #        if pyro :
        #            tpgeom.MakeTag(c4d.Ttexture)
        #            tag[1010] = c4d.BaseMaterial(1001005)

    def pyro(self):
        pass

        ############DYNAMICS ##############################

        # ==============================================================================

    # Dynamics simulation
    # ==============================================================================
    def setRigidBody(self, obj, shape="auto", child=False,
                     dynamicsBody="on", dynamicsLinearDamp=0.0,
                     dynamicsAngularDamp=0.0,
                     massClamp=0.0, rotMassClamp=1.0):
        if type(obj) is str:
            obj = self.getObject(obj)
        # The object 'Dynamics Body' (DynRigidBodyTag) was added as 'DynamicsBody'.
        tag = obj.MakeTag(self.DYNAMIC)
        if child:
            tag[c4d.RIGID_BODY_HIERARCHY] = 1  # for cpk
            tag[c4d.RIGID_BODY_SPLIT_CACHE] = 0  # None
        else:
            tag[c4d.RIGID_BODY_HIERARCHY] = 2  # for cpk
            tag[c4d.RIGID_BODY_SPLIT_CACHE] = 1  # Top level
            tag[c4d.RIGID_BODY_LINEAR_FOLLOW_STRENGTH] = 60
            tag[c4d.RIGID_BODY_ANGULAR_FOLLOW_STRENGTH] = 60
        tag[c4d.RIGID_BODY_SELF_COLLISIONS] = 0
        if shape == "auto":
            tag[c4d.RIGID_BODY_SHAPE] = 11  # automatic , 4-static shape
        elif shape == "static":
            tag[c4d.RIGID_BODY_SHAPE] = 4  # automatic , 4-static shape
        if dynamicsLinearDamp > 0:
            tag[c4d.RIGID_BODY_LINEAR_DAMPING] = dynamicsLinearDamp
        if dynamicsAngularDamp > 0:
            tag[c4d.RIGID_BODY_ANGULAR_DAMPING] = dynamicsAngularDamp
        if massClamp > 0:
            tag[c4d.RIGID_BODY_MASS_SWITCH] = 2
            tag[c4d.RIGID_BODY_MASS] = massClamp
            tag[c4d.RIGID_BODY_INERTIA_FACTOR] = rotMassClamp
            tag[c4d.RIGID_BODY_SELF_COLLISIONS] = 1
        if dynamicsBody == "off":
            tag[c4d.RIGID_BODY_DYNAMIC] = 0  # 2=ghost, 1= on, 0= off
        return tag

    def setSoftBody(self, obj):
        # The object 'Dynamics Body' (DynRigidBodyTag) was added as 'DynamicsBody'.
        if type(obj) is str:
            obj = self.getObject(obj)
        tag = obj.MakeTag(self.DYNAMIC)
        tag[c4d.RIGID_BODY_HIERARCHY] = 0  #
        tag[c4d.RIGID_BODY_SPLIT_CACHE] = 0  #
        tag[c4d.RIGID_BODY_LINEAR_FOLLOW_STRENGTH] = 0
        tag[c4d.RIGID_BODY_ANGULAR_FOLLOW_STRENGTH] = 10
        tag[c4d.RIGID_BODY_SELF_COLLISIONS] = 0
        tag[c4d.RIGID_BODY_SPECIFIC_MARGIN] = 1
        tag[c4d.RIGID_BODY_MARGIN] = 1.8
        tag[c4d.RIGID_BODY_SOFT] = 1  # made of polygin/lines
        tag[c4d.RIGID_BODY_SB_SHAPE_CONSERVATION] = 20.0
        return tag

    def updateSpring(self, spring, targetA=None, tragetB=None,
                     rlength=0.0, stifness=1., damping=1.0):
        if targetA is not None:
            spring[c4d.FORCE_OBJECT_A] = targetA
        spring[c4d.FORCE_APPLICATION_A] = 0  # center of Mass
        if tragetB is not None:
            spring[c4d.FORCE_OBJECT_B] = tragetB
        spring[c4d.FORCE_APPLICATION_B] = 1  # offset
        spring[c4d.FORCE_APPLY] = 1  # only to B
        spring[c4d.SPRING_LINEAR_REST_LENGTH] = rlength
        spring[c4d.SPRING_LINEAR_STIFFNESS] = stifness
        spring[c4d.SPRING_LINEAR_DAMPING] = damping

    def createSpring(self, name, targetA=None, tragetB=None,
                     rlength=0.0, stifness=1.0, damping=1.0, parent=None):
        spring = c4d.BaseObject(self.SPRING)
        spring.SetName(name)
        spring[c4d.FORCE_TYPE] = 0  # linear
        if targetA is not None:
            spring[c4d.FORCE_OBJECT_A] = targetA
        spring[c4d.FORCE_APPLICATION_A] = 0  # center of Mass
        if tragetB is not None:
            spring[c4d.FORCE_OBJECT_B] = tragetB
        spring[c4d.FORCE_APPLICATION_B] = 1  # offset
        spring[c4d.FORCE_APPLY] = 1  # only to B
        spring[c4d.SPRING_LINEAR_REST_LENGTH] = rlength
        spring[c4d.SPRING_LINEAR_STIFFNESS] = stifness
        spring[c4d.SPRING_LINEAR_DAMPING] = damping
        self.addObjectToScene(None, spring, parent=parent)
        return spring

    def addConstraint(self, obj, type="spring", target=None):
        if type(obj) is str:
            obj = self.getObject(obj)
        tag = obj.MakeTag(self.CONTRAINT)
        if type == "spring":
            tag[c4d.ID_CA_CONSTRAINT_TAG_SPRING]
            tag[c4d.ID_CA_CONSTRAINT_TAG_SPRING_TWEIGHT]  # strenghth
            tag[c4d.ID_CA_CONSTRAINT_TAG_SPRING_DRAG]  # drag
            # offset can be P,S,R X,Y,Z
            tag[c4d.ID_CA_CONSTRAINT_TAG_SPRING_P_OFFSET, VECTOR_X]  # offset X,
            if target is not None:
                # id are [60006] based
                # how to add a target
                tag[c4d.ID_CA_CONSTRAINT_TAG_SPRING_TARGET_COUNT] = len(target)
                id = 60000
                for t in target:
                    tag[id + 1] = self.getObject(t)  # target object first target
                    tag[id + 2]  # weigth first target
                    tag[id + 4]  # length first target
                    tag[id + 5]  # stiffness first target
                    tag[id + 6]  # position toggle first target
                    tag[id + 7]  # scale toggle first target
                    tag[id + 8]  # rotation toggle first target
                    id += 10

                    # ===============================================================================
                # animation features
                # ===============================================================================

    def setKeyFrame(self, obj, **kw):
        self.setCurrentSelection(obj)
        c4d.CallCommand(self.RECORD)

    def setFrame(self, value):
        doc = self.getCurrentScene()
        fps = doc.GetFps()
        t = c4d.BaseTime(float(value) / float(fps))
        doc.SetTime(t)
        self.update()

    def frameAdvanced(self, doc=None, duration=None, display=False, cb=None):
        if doc is None:
            doc = self.getCurrentScene()
        fps = doc.GetFps()
        done = False
        i = 0
        while not done:
            # for i in range(duration):
            if duration is not None:
                if i >= duration:
                    done = True
                    break
            t = c4d.BaseTime(float(i) / float(fps))
            doc.SetTime(t)
            c4d.DrawViews(c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_NO_REDUCTION | c4d.DRAWFLAGS_STATICBREAK)
            # c4d.DRAWFLAGS_PRIVATE_OPENGLHACK)#|c4d.DRAWFLAGS_NO_THREAD|c4d.DRAWFLAGS_NO_REDUCTION|c4d.DRAWFLAGS_STATICBREAK)#|c4d.DRAWFLAGS_ONLY_ACTIVE_VIEW
            # c4d.EventAdd(c4d.EVENT_ANIMATE)
            # do your caching here. 'f' is the current frame
            if cb is not None:
                done = cb()
            #            c4d.EventAdd(c4d.EVENT_0)
            # c4d.EventAdd(c4d.EVENT_ANIMATE|c4d.EVENT_GLHACK)
            # c4d.DrawViews(c4d.DRAWFLAGS_PRIVATE_OPENGLHACK)
            c4d.GeSyncMessage(c4d.EVMSG_TIMECHANGED)
            #            c4d.EventAdd(c4d.EVENT_ANIMATE)
            if display:
                self.update()
            i = i + 1
        # t=c4d.BaseTime(0.)
        # doc.SetTime(t)
        c4d.EventAdd(c4d.EVENT_ANIMATE)

    def animationStart(self, doc=None, forward=True, duration=None):
        if doc is None:
            doc = self.getCurrentScene()
        from time import time
        starttime = time()
        c4d.documents.RunAnimation(doc, False, forward)
        if duration is not None:
            done = False
            # fps = doc.GetFps()
            # startframe=doc.GetTime().GetFrame(fps)
            while not done:
                #                t=c4d.BaseTime()
                #                fps = doc.GetFps()
                #                #getCurrent time
                #                frame=doc.GetTime().GetFrame(fps)
                newtime = time()
                if newtime - starttime >= 10.0:
                    done = True
                    break
            self.animationStop()

    def animationStop(self, doc=None):
        if doc is None:
            doc = self.getCurrentScene()
        c4d.documents.RunAnimation(doc, True)

        # ===============================================================================

    #     Texture Mapping / UV
    # ===============================================================================
    def getUV(self, object, faceIndex, vertexIndex, perVertice=True):
        ob = self.getObject(object)
        # uv=[]
        tag = ob.GetTag(c4d.Tuvw)
        if tag is None:
            tag = object.MakeVariableTag(c4d.Tuvw, ob.GetPolygonCount(), object.GetFirstTag())
            # vtag.SetName("uvTag")
        uvs = tag.GetSlow(faceIndex)
        if perVertice:
            for j, k in enumerate(uvs):
                if j == vertexIndex:
                    return self.ToVec(uvs[k], pos=False)
        else:
            return [self.ToVec(uvs[k], pos=False) for k in uvs]

    def setUV(self, object, faceIndex, vertexIndex, uv, perVertice=True, uvid=0):
        ob = self.getObject(object)
        # uv is per polygon
        tag = ob.GetTag(c4d.Tuvw)
        if tag is None:
            tag = object.MakeVariableTag(c4d.Tuvw, ob.GetPolygonCount(), object.GetFirstTag())
            # vtag.SetName("uvTag")
        if perVertice:
            uvs = tag.GetSlow(faceIndex)
            for j, k in enumerate(uvs):
                if j == vertexIndex:
                    uvs[k] = self.FromVec(uv, pos=False)
            tag.SetSlow(faceIndex, uvs["a"], uvs["b"], uvs["c"], uvs["d"])
        else:
            uvs = [self.FromVec(x, pos=False) for x in uv]
            tag.SetSlow(faceIndex, uvs[0], uvs[1], uvs[2], uvs[3])  # for a face
        # print faceIndex
        tag.Message(c4d.MSG_UPDATE)

        # ==============================================================================

    #   obj properties
    # ==============================================================================
    def getPropertyObject(self, obj, **keys):
        """
        Return the  property "key" of the object obj

        * overwrited by children class for each host

        @type  obj: host Obj
        @param obj: the object that contains the property
        @type  key: string
        @param key: name of the property

        @rtype  : int, float, str, dict, list
        @return : the property value
        """
        res = []
        key = keys['key']
        # print ("get object parameters ",keys,key)
        if "pos" in key:
            res.append(self.ToVec(self.getTranslation(obj)))
        if "scale" in key:
            res.append(self.ToVec(self.getScale(obj), pos=False))

        if "rotation" in key:
            mo = self.getTransformation(obj)
            m = self.ToMat(mo)  # .transpose()
            mws = m.transpose()  # Transpose ?
            rotMatj = mws[:]
            rotMatj[3][:3] *= 0.0
            res.append(rotMatj)
        if obj.GetType() == self.SPHERE:
            for k in key:
                if k == "radius":
                    res.append(obj[self.PRIM_SPHERE_RAD])
        if obj.GetType() == self.CYLINDER:
            for k in key:
                if k == "radius":
                    res.append(obj[5000])
                elif k == "length":
                    res.append(obj[5005])
                elif k == "axis":
                    listeAxis = ["+X", "-X",
                                 "+Y", "-Y",
                                 "+Z", "-Z"]
                    dic = {"+X": [1., 0., 0.], "-X": [-1., 0., 0.], "+Y": [0., 1., 0.], "-Y": [0., -1., 0.],
                           "+Z": [0., 0., 1.], "-Z": [0., 0., -1.]}
                    ax = obj[c4d.PRIM_AXIS]
                    res.append(dic[listeAxis[ax]])
        if obj.GetType() == self.CUBE:
            for k in key:
                if k == "length":
                    res.append(obj[c4d.PRIM_CUBE_LEN])
        return res

        # ===============================================================================

    # userData property for object, persistent in scene saved
    # ===============================================================================

    def retrievePropertiesFromContainer(self, container, typ):
        pass

    def getProperty(self, obj, key, typ=dict):
        obj = self.getObject(obj)
        if not isinstance(key, str):
            raise TypeError, "expected a str for the key argument"
        # get object userDAta
        propertiesListe = obj.GetUserDataContainer()
        for bc in propertiesListe:
            if bc[c4d.DESC_NAME] == key:
                return self.retrievePropertiesFromContainer(bc, typ)
        return None

    def setProperty(self, obj, key, value):
        cool_value_types = (int, float, str, dict, list)

        def check_property_values(value, name):
            "Recursively check property types and values"
            if not isinstance(value, (int, float, str, dict, list)):
                raise TypeError, "expected a %s for the property: %s" % \
                                 (", ".join("%s" % t.__name__ for t in cool_value_types), name)

            if isinstance(value, dict):
                for key, val in value.iteritems():
                    check_properties(val, name + "['%s']" % key)
                #            if isinstance(value, (list, str)) and len(value) > 10000:
                #                raise ValueError, "property: %s is a %s which is "\
                #                      "too long. Max size: 10000 "%(name, str(type(value)))

        if not isinstance(key, str):
            raise TypeError, "expected a str for the key argument"

        check_property_values(value, key)
        # GetCustomDatatypeDefault
        obj.properties[key] = value

    # from r13 documentation
    def AddLongDataType(obj):
        if obj is None: return

        bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)  # create default container
        bc[c4d.DESC_NAME] = "Test"  # rename the entry

        element = obj.AddUserData(bc)  # add userdata container
        obj[element] = 30  # assign a value
        c4d.EventAdd()  # update

        # ===============================================================================

    # deformer
    # ===============================================================================
    def pathDeform(self, name, obj, curve, **kw):
        """ deform an object along a path
        @type  obj: hostObj
        @param obj: the object to be deform
        @type  curve: hostObj
        @param curve: the path

        @rtype:   hostObj
        @return:  the path deformer modifier
        """
        # create the path deformer object
        pathD = self.getObject(name)
        if pathD is None:
            pathD = c4d.BaseObject(self.PATHDEFORM)
            pathD.SetName(name)
            self.addObjectToScene(pathD, parent=obj)
        pathD[c4d.MGSPLINEWRAPDEFORMER_SPLINE] = curve
        pathD[c4d.MGSPLINEWRAPDEFORMER_LENMODE] = 1  # Keep Length
        return pathD

    def updatePathDeform(self, name, **kw):
        """ update a path deformer
        @type  name: hostObj/string
        @param obj: the object to be deform
        @type  kw: dictionary
        @param kw: the attributes to change

        @rtype:   hostObj
        @return:  the path deformer modifier
        """
        pathD = self.getObject(name)
        if pathD is None:
            return
        if kw.has_key("spline"):
            pathD[c4d.MGSPLINEWRAPDEFORMER_SPLINE] = kw["spline"]
        if kw.has_key("keep_length"):
            pathD[c4d.MGSPLINEWRAPDEFORMER_LENMODE] = kw["keep_length"]  # 0 or 1
        if kw.has_key("object"):
            self.reParent(pathD, kw["object"])

            # ==============================================================================
        # Noise
        # ==============================================================================

    def get_noise(self, point, ntype, nbasis, dimension=1.0, lacunarity=2.0, offset=1.0, octaves=6, gain=1.0, **kw):
        # multi_fractal(position, H, lacunarity, octaves, noise_basis=noise.types.STDPERLIN)
        # NotePlease use InitFbm() before you use one of the following noise types:
        # NOISE_ZADA, NOISE_DISPL_VORONOI, NOISE_OBER, NOISE_FBM, NOISE_BUYA.

        nbasis = self.noise_type.values()[nbasis]

        theNoise = C4DNoise(nbasis)
        # InitFbm(lMaxOctaves, rLacunarity, h)
        theNoise.InitFbm(21, lacunarity, dimension)

        depth = octaves
        value = 0.0
        x, y, z = point
        vlbasis = nbasis
        point = self.FromVec(point)
        if ntype == 0:
            # Noise(t, two_d, p[, time=0.0][, octaves=4.0][, absolute=False][, sampleRad=0.25][, detailAtt=0.25][, repeat=0])
            # r = p.Noise(noisetype, False, c4d.Vector(x/rw, y/rh, 0) * 7.0, octaves=5)
            value = theNoise.Noise(nbasis, False, point, octaves=float(depth)) * 0.5
        elif ntype == 1:
            value = theNoise.RidgedMultifractal(point, depth, offset, gain, 1) * 0.5
        #            value = ridged_multi_fractal( point, dimension, lacunarity, depth, offset, gain, nbasis ) * 0.5
        elif ntype == 2:
            # Turbulence(p, rOctaves, bAsolute[, t=0.0])
            value = theNoise.Turbulence(point, depth, offset, gain) * 0.5
        elif ntype == 3:
            # SNoise(p, lRepeat[, t=0.0])
            value = theNoise.SNoise(point, offset, gain) * 0.5
        elif ntype == 4:
            # Fbm(p, rOctaves, lRepeat[, t=0.0])
            value = theNoise.Fbm(point, depth, offset, gain)
        #            value = fractal(point, dimension, lacunarity, depth, nbasis )
        #        elif ntype == 5: value = turbulence_vector(    point, depth, hardnoise, nbasis )[0]
        #        elif ntype == 6: value = variable_lacunarity(  point, distortion, nbasis, vlbasis ) + 0.5
        #        elif ntype == 7: value = self.marble_noise( x*2.0/falloffsize,y*2.0/falloffsize,z*2/falloffsize, origin, nsize, marbleshape, marblebias, marblesharpnes, distortion, depth, hardnoise, nbasis )
        #        elif ntype == 8: value = self.shattered_hterrain( point[0], point[1], point[2], dimension, lacunarity, depth, offset, distortion, nbasis )
        #        elif ntype == 9: value = self.strata_hterrain( point[0], point[1], point[2], dimension, lacunarity, depth, offset, distortion, nbasis )
        return value

        # ===============================================================================

    # Function dependant on numpy
    # ===============================================================================
    #    if usenumpy:
    def matrix2c4dMat(self, mat, transpose=True):
        # Scale Problem, but shouldnt as I decompose???
        # why do I transpose ?? => fortran matrix ..
        if not self._usenumpy:
            return self.FromMat(mat, transpose=transpose)
        if transpose:
            mat = numpy.array(mat).transpose().reshape(16, )
        else:
            mat = numpy.array(mat).reshape(16, )
        r, t, s = self.Decompose4x4(mat)
        #        print s
        # Order of euler angles: heading first, then attitude/pan, then bank
        #            axis = self.ApplyMatrix(numpy.array([[1.,0.,0.],[0.,1.,0.],[0.,0.,1.]]),r.reshape(4,4))
        # r = numpy.identity(4).astype('f')
        # M = matrix(matr)
        # euler = C.matrixToEuler(mat[0:3,0:3])
        # mx=c4d.tools.hpb_to_matrix(c4d.Vector(euler[0],euler[1]+(3.14/2),euler[2]), c4d.tools.ROT_HPB)
        v_1 = self.FromVec(r.reshape(4, 4)[2, :3])
        v_2 = self.FromVec(r.reshape(4, 4)[1, :3])
        v_3 = self.FromVec(r.reshape(4, 4)[0, :3])
        offset = self.FromVec(t)
        mx = c4d.Matrix(offset, v_1, v_2, v_3)
        # mx.off = offset
        return mx

    def FromMat(self, matrice, transpose=True):
        #            import numpy
        # Scale Problem, but shouldnt as I decompose???
        # why do I transpose ?? => fortran matrix ..
        if self._usenumpy:
            v_1 = self.FromVec(matrice[2, :3])
            v_2 = self.FromVec(matrice[1, :3])
            v_3 = self.FromVec(matrice[0, :3])
            offset = self.FromVec(matrice[3, :3])
        else:
            v_1 = self.FromVec(matrice[2][:3])
            v_2 = self.FromVec(matrice[1][:3])
            v_3 = self.FromVec(matrice[0][:3])
            offset = self.FromVec(matrice[3][:3])
        mx = c4d.Matrix(offset, v_1, v_2, v_3)
        return mx

    def DecomposeMesh(self, poly, edit=True, copy=True, tri=True, transform=True, fn=False):
        # make it editable
        poly = self.getMesh(poly)
        #        print ("Decompose",poly,poly.GetType(),poly.GetType() == c4d.Opolygon)

        if edit:
            poly = self.makeEditable(poly, copy=copy)
            # here problem when name is identic with parent and mesh
            poly = self.getMesh(self.getObject(self.getName(poly)))
        # triangulate
        if tri:
            self.triangulate(poly)
        # get infos

        # check the polycache
        cach = poly.GetCache()
        if cach is None:
            cach = poly.GetDeformCache()
        if cach is not None:
            poly = cach
        print poly, self.getName(poly)
        faces = self.getFaces(poly)
        vertices = self.getMeshVertices(poly, selected=False)
        # this require that the phong tag is present
        phong = poly.GetTag(c4d.Tphong)
        if phong is None:
            poly.MakeTag(c4d.Tphong)
        c4dvnormals = poly.CreatePhongNormals()  # len(f)*4
        if not c4dvnormals:
            print poly, self.getName(poly)
        vnormals = vertices[:]
        fnormals = []
        # import numpy

        for i, f in enumerate(faces):
            # one face : 3/4 vertices
            if self._usenumpy:
                fns = numpy.zeros((len(f), 3))
            else:
                fns = []
            for k, j in enumerate(f):
                # print i,j,(i*4)+k
                vnormals[j] = self.ToVec(c4dvnormals[(i * 4) + k])
                if self._usenumpy:
                    fns[k][:] = vnormals[j][:]
                else:
                    fns.append(vnormals[j][:])
            fnormals.append(fns[-1])
        #            if  self._usenumpy: fnormals.append(numpy.average(fns,0))
        #            else  : fnormals.append(fns[-1])
        # remove the copy if its exist? or keep it ?
        # need to apply the transformation
        #        vnormals=self.FixNormals(vertices,faces, vnormals,fn=fnormals)# v,f,vn
        if transform:
            # transpose ?
            mat = self.getTransformation(poly)
            # c4dmat = poly.GetMg()
            # mat,imat = self.c4dMat2numpy(c4dmat)
            vertices = self.ApplyMatrix(vertices, self.ToMat(mat))
            m = numpy.identity(4)
            m[:3, :3] = numpy.array(self.ToMat(mat))[:3, :3]
            vnormals = self.ApplyMatrix(vnormals, m)  # rotation only ?
        # fix the normals ?
        if edit and copy:
            self.getCurrentScene().SetActiveObject(poly)
            c4d.CallCommand(100004787)  # delete the obj
        if fn:
            return faces, vertices, vnormals, fnormals
        else:
            return faces, vertices, vnormals

    def ApplyMatrix(self, coords, mat):
        """
        Apply the 4x4 transformation matrix to the given list of 3d points.

        @type  coords: array
        @param coords: the list of point to transform.
        @type  mat: 4x4array
        @param mat: the matrix to apply to the 3d points

        @rtype:   array
        @return:  the transformed list of 3d points
        """
        if self._usenumpy:
            return Helper.ApplyMatrix(self, coords, mat)
        else:
            mat = self.FromMat(mat)
            return [mat.Mul(self.FromVec(c)) for c in coords]

    def rotation_matrix(self, angle, direction, point=None, trans=None):
        """
        Return matrix to rotate about axis defined by point and direction.

        """
        if self._usenumpy:
            return Helper.rotation_matrix(angle, direction, point=point, trans=trans)
        else:
            direction = self.FromVec(direction[:3])
            direction.Normalize()
            M = c4d.utils.RotAxisToMatrix(direction, angle)
            # M = m.copy()
            if point is not None:
                point = self.FromVec(point[:3])
                M.off = point - (point * M)
            if trans is not None:
                M.off = trans
            return M

    def zToMat(self, m):
        if type(m) != c4d.Matrix:
            return m
        M = numpy.identity(4)
        M[0, :3] = self.ToVec(m.v1, pos=False)
        M[1, :3] = self.ToVec(m.v2, pos=False)
        M[2, :3] = self.ToVec(m.v3, pos=False)
        M[3, :3] = self.ToVec(m.off, pos=False)
        return M

    def ToMat(self, m, transpose=True):
        if type(m) != c4d.Matrix:
            return m
        if self._usenumpy:
            return self.c4dMat2numpy(m, transpose=transpose)
        M = [[1.0, 0., 0.0, 0.0],
             [0.0, 1., 0.0, 0.0],
             [0.0, 0., 1.0, 0.0],
             [0.0, 0., 0.0, 1.0]]
        M[2][:3] = self.ToVec(m.v1)
        M[1][:3] = self.ToVec(m.v2)
        M[0][:3] = self.ToVec(m.v3)
        M[3][:3] = self.ToVec(m.off)
        if transpose:
            return M  # .transpose()
        else:
            return M

    def c4dMat2numpy(self, c4dmat, transpose=True, center=None):
        """a c4d matrice is
        v1     X-Axis
        v2     Y-Axis
        v3     Z-Axis
        off     Position
        a numpy matrice is a regular 4x4 matrice (3x3rot+trans)
        """
        import numpy
        # print "ok convertMAtrix"
        from numpy import matrix
        M = numpy.identity(4)
        M[2, :3] = self.ToVec(c4dmat.v1)
        M[1, :3] = self.ToVec(c4dmat.v2)
        M[0, :3] = self.ToVec(c4dmat.v3)
        trans = self.ToVec(c4dmat.off)
        if center != None:
            for i in range(3):
                trans[i] = trans[i] - center[i]
        M[3, :3] = trans
        if transpose:
            M = M.transpose()
        return M

    def getMatRotation(self, obj, transpose=True):
        R = numpy.identity(4)
        #        R=[[1.0,0.,0.0,0.0],
        #           [0.0,1.,0.0,0.0],
        #           [0.0,0.,1.0,0.0],
        #           [0.0,0.,0.0,1.0]]
        obj = self.getObject(obj)
        objdcache = obj.GetDeformCache()
        objcache = obj.GetCache()
        #        print "cache1",objdcache,"cache2",objcache
        #        print "dirty MAtrix",obj.IsDirty(c4d.DIRTY_MATRIX)
        if objdcache is not None:
            print "cache1"
            m = objdcache.GetMg()
        elif objcache is not None:
            print "cache2"
            m = objcache.GetMg()
        else:
            m = obj.GetMg()
        #        R = self.ToMat(m,transpose=transpose)
        R[2, :3] = self.ToVec(m.v1)  # thi work with numpy
        R[1, :3] = self.ToVec(m.v2)
        R[0, :3] = self.ToVec(m.v3)
        # euler = c4d.utils.MatrixToHPB(c4dmat) #heading,att,bank need to inverse y/z left/righ hand problem
        # print "euler",euler
        # matr = numpy.array(self.eulerToMatrix([euler.x,euler.z,euler.y]))
        if transpose:
            return R.transpose()  # this wilnot work
        else:
            return R

    def read(self, filename, **kw):
        #        fileName, fileExtension = os.path.splitext(filename)
        doc = self.getCurrentScene()
        #        print self
        #        print doc ,doc.IsAlive()
        #        print c4d.documents.GetActiveDocument(),c4d.documents.GetActiveDocument().IsAlive()
        c4d.documents.MergeDocument(doc, str(filename), c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS)

    #        else :
    #            c4d.documents.LoadFile(filename)
    #            doc2 = self.getCurrentScene()
    #            #save in c4d
    #            c4d.documents.SaveDocument(doc2,fileName+".c4d",c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST,c4d.FORMAT_C4DEXPORT)
    #            #close
    #            c4d.documents.KillDocument(doc2)
    #            #merge
    #            c4d.documents.MergeDocument(doc,fileName+".c4d",c4d.SCENEFILTER_OBJECTS|c4d.SCENEFILTER_MATERIALS)

    def write(self, filename, listObj, formatType="host", **kw):
        #        FORMAT_C4DEXPORT	C4D export.
        #        FORMAT_XMLEXPORT	XML export.
        #        FORMAT_VRML1EXPORT	VRML export.
        #        FORMAT_VRML2EXPORT	VRML export.
        #        FORMAT_DXFEXPORT	DXF export.
        #        FORMAT_3DSEXPORT	3DS export.
        #        FORMAT_OBJEXPORT	OBJ export.
        #        FORMAT_Q3DEXPORT	QuickDraw 3D export
        #        FORMAT_D3DEXPORT	Direct3D import
        fType = {"host": c4d.FORMAT_C4DEXPORT,}
        fileName, fileExtension = os.path.splitext(filename)
        doc = self.getCurrentScene()
        format = fType[formatType]
        if listObj is None or not listObj:
            c4d.documents.SaveDocument(doc, filename, c4d.SAVEDOCUMENTFLAGS_0, format)
        else:
            newdoc = c4d.documents.IsolateObjects(doc, listObj)
            c4d.documents.SaveDocument(newdoc, filename, c4d.SAVEDOCUMENTFLAGS_0, format)

    def ObjectToColladaNode(self, o):
        # conver C4D ob and child to a collada node that can be used by instance_node
        pass

    def writeCollada(self, collada_xml, filename, **kw):
        collada_xml.write(filename)

    def instancesToCollada(self, parent_object, collada_xml=None, instance_node=True, **kw):
        try:
            from upy.transformation import decompose_matrix
            from collada import Collada
            from collada import material
            from collada import source
            from collada import geometry
            from collada import scene
        except:
            return
        inst_parent = parent_object  # self.getCurrentSelection()[0]
        ch = self.getChilds(inst_parent)
        # instance master
        inst_master = self.getMasterInstance(ch[0])
        # grabb v,f,n of inst_master
        f, v, vn = self.DecomposeMesh(inst_master, edit=False, copy=False, tri=True,
                                      transform=True)

        iname = self.getName(inst_master)
        pname = self.getName(inst_parent)
        if collada_xml is None:
            collada_xml = Collada()
            collada_xml.assetInfo.unitname = "centimeter"
            collada_xml.assetInfo.unitmeter = 0.01
        mat = self.getMaterialObject(inst_master)
        if len(mat):
            mat = mat[0]
        props = self.getMaterialProperty(mat, diffuse=1, specular_color=1)
        effect = material.Effect("effect" + iname, [], "phong",
                                 diffuse=props["diffuse"],
                                 specular=props["specular_color"])
        mat = material.Material("material" + iname, iname + "_material", effect)
        matnode = scene.MaterialNode("material" + iname, mat, inputs=[])
        collada_xml.effects.append(effect)
        collada_xml.materials.append(mat)
        # the geom
        # invert Z
        vertzyx = numpy.array(v)  # * numpy.array([1,1,-1])
        z, y, x = vertzyx.transpose()
        vertxyz = numpy.vstack([x, y, z]).transpose() * numpy.array([1, 1, -1])
        vert_src = source.FloatSource(iname + "_verts-array", vertxyz.flatten(), ('X', 'Y', 'Z'))
        norzyx = numpy.array(vn)
        nz, ny, nx = norzyx.transpose()
        norxyz = numpy.vstack([nx, ny, nz]).transpose() * numpy.array([1, 1, -1])
        normal_src = source.FloatSource(iname + "_normals-array", norxyz.flatten(), ('X', 'Y', 'Z'))
        geom = geometry.Geometry(collada_xml, "geometry" + iname, iname, [vert_src, normal_src])
        input_list = source.InputList()
        input_list.addInput(0, 'VERTEX', "#" + iname + "_verts-array")
        input_list.addInput(0, 'NORMAL', "#" + iname + "_normals-array")
        # invert all the face
        fi = numpy.array(f, int)  # [:,::-1]
        triset = geom.createTriangleSet(fi.flatten(), input_list, iname + "materialref")
        geom.primitives.append(triset)
        collada_xml.geometries.append(geom)
        # the  noe
        # instance here ?
        # creae the instance maser node :
        if instance_node:
            master_geomnode = scene.GeometryNode(geom, [matnode])
            master_node = scene.Node("node_" + iname, children=[master_geomnode, ])  # ,transforms=[tr,rz,ry,rx,s])
        g = []
        for c in ch:
            # collada.scene.NodeNode
            if instance_node:
                geomnode = scene.NodeNode(master_node)
            else:
                geomnode = scene.GeometryNode(geom, [matnode])
            matrix = self.zToMat(self.getTransformation(c))  # .transpose()#.flatten()
            scale, shear, euler, translate, perspective = decompose_matrix(matrix.transpose())
            scale = self.getScale(c)
            p = translate  # matrix[3,:3]/100.0#unit problem
            tr = scene.TranslateTransform(p[0], p[1], -p[2])
            rx = scene.RotateTransform(-1, 0, 0, numpy.degrees(euler[0]))
            ry = scene.RotateTransform(0, -1, 0, numpy.degrees(euler[1]))
            rz = scene.RotateTransform(0, 0, 1, numpy.degrees(euler[2]))
            s = scene.ScaleTransform(scale[0], scale[1], scale[2])
            # n = scene.NodeNode(master_node,transforms=[tr,rz,ry,rx,s])
            n = scene.Node(self.getName(c), children=[geomnode, ],
                           transforms=[tr, rz, ry, rx, s])  # scene.MatrixTransform(matrix)
            g.append(n)
        node = scene.Node(pname, children=g)  # ,transforms=[scene.RotateTransform(0,1,0,90.0)])
        if "parent_node" in kw:
            kw["parent_node"].children.append(node)
            node = kw["parent_node"]
        if not len(collada_xml.scenes):
            myscene = scene.Scene("myscene", [node])
            collada_xml.scenes.append(myscene)
            collada_xml.scene = myscene
        else:
            if "parent_node" not in kw:
                collada_xml.scene.nodes.append(node)
        if instance_node:
            collada_xml.nodes.append(master_node)
        return collada_xml

    def raycast(self, obj, start, end, length, **kw):
        obj = self.getObject(obj)
        mat = self.getTransformation(obj).__invert__()
        coll = c4d.utils.GeRayCollider()
        coll.Init(obj)
        start = self.FromVec(start)
        end = self.FromVec(end)
        #        print start,end,end-start
        intersect = coll.Intersect(mat * start, mat * (end - start), length)  # [, only_test=False])
        if not intersect:
            return intersect, 0
        if "count" in kw:
            return intersect, coll.GetIntersectionCount()
        if "fnormal" in kw:
            ray_result = coll.GetNearestIntersection()
            n = ray_result["f_normal"].GetNormalized()
            return intersect, self.ToVec(n)
        if "hitpos" in kw:
            ray_result = coll.GetNearestIntersection()
            return intersect, self.ToVec(ray_result["hitpos"])
        return intersect

    #        self.rc = utils.GeRayCollider()#helper ?
    #        self.rc.Init(input_mesh)

    def removeNormalTag(self, obj, **kw):
        obj = self.getObject(obj)
        #        tags = obj.GetTags(c4d.Tnormal)
        obj.KillTag(c4d.Tnormal)


# tokill=[]
#        for i,t in enumerate(tags):
#            if isinstance(t,c4d.NormalTag):
#                tokill.append(i)
#        [obj.KillTag(i) for i in tokill]

import time


class TimerDialog(c4d.gui.SubDialog):
    """
    Timer dialog for c4d, wait time for user input.
    from Pmv.hostappInterface.cinema4d_dev import helperC4D as helper
    dial = helper.TimerDialog()
    dial.cutoff = 30.0
    dial.Open(c4d.DLG_TYPE_ASYNC, pluginid=3555550, defaultw=250, defaulth=100)
    """

    def init(self):
        self.startingTime = time.time()
        self.dT = 0.0
        self._cancel = False
        self.SetTimer(100)  # miliseconds
        # self.cutoff = ctime #seconds
        # self.T = int(ctime)

    def initWidgetId(self):
        id = 1000
        self.BTN = {"No": {"id": id, "name": "No", 'width': 50, "height": 10,
                           "action": self.continueFill},
                    "Yes": {"id": id + 1, "name": "Yes", 'width': 50, "height": 10,
                            "action": self.stopFill},
                    }
        id += len(self.BTN)
        self.LABEL_ID = [{"id": id, "label": "Did you want to Cancel the Filling Job:"},
                         {"id": id + 1, "label": str(self.cutoff)}]
        id += len(self.LABEL_ID)
        return True

    def CreateLayout(self):
        ID = 1
        self.SetTitle("Cancel?")
        self.initWidgetId()
        # minimize otin/button
        self.GroupBegin(id=ID, flags=c4d.BFH_SCALEFIT | c4d.BFV_MASK,
                        cols=2, rows=10)
        self.GroupBorderSpace(10, 10, 5, 10)
        ID += 1
        self.AddStaticText(self.LABEL_ID[0]["id"], flags=c4d.BFH_LEFT)
        self.SetString(self.LABEL_ID[0]["id"], self.LABEL_ID[0]["label"])
        self.AddStaticText(self.LABEL_ID[1]["id"], flags=c4d.BFH_LEFT)
        self.SetString(self.LABEL_ID[1]["id"], self.LABEL_ID[1]["label"])
        ID += 1

        for key in self.BTN.keys():
            self.AddButton(id=self.BTN[key]["id"], flags=c4d.BFH_LEFT | c4d.BFV_MASK,
                           initw=self.BTN[key]["width"],
                           inith=self.BTN[key]["height"],
                           name=self.BTN[key]["name"])
        self.init()
        return True

    def open(self):
        self.Open(c4d.DLG_TYPE_MODAL, pluginid=25555589, defaultw=120, defaulth=100)

    def Timer(self, val):
        # print val val seem to be the gadget itself ?
        # use to se if the user answer or not...like of nothing after x ms
        # close the dialog
        #        self.T -= 1.0
        curent_time = time.time()
        self.dT = curent_time - self.startingTime
        #        print self.dT, self.T
        self.SetString(self.LABEL_ID[1]["id"], str(self.cutoff - self.dT))
        if self.dT > self.cutoff:
            self.continueFill()

    def stopFill(self):
        self._cancel = True
        self.Close()

    def continueFill(self):
        self._cancel = False
        self.Close()

    def Command(self, id, msg):
        for butn in self.BTN.keys():
            if id == self.BTN[butn]["id"]:
                self.BTN[butn]["action"]()
        return True
