xs_yann
01/10/2014, 16h34
Salut à tous,
Je vous partage un petit exercice Python que j’ai fait, qui consiste à recoder La PointeuseX™ de Jean-Laurent en Python.
http://frenchcinema4d.fr/showthread.php?57408-Compteur-temps-pass%E9
Le principe de Jean-Laurent était de comparer à chaque exécution la minute courante avec celle de l’exécution précédente et en cas de différence (une ou plusieurs minutes écoulées), ajouter cette différence au compteur.
Le principe que j’ai utilisé est de calculer le temps écoulé entre chaque exécution (aussi court soit-il) et de l’ajouter au compteur.
http://www.xsyann.com/fc4d/pointeusey_gui.png
Valeur : La valeur courante du compteur (il est possible de la modifier manuellement).
Inactivité : Temps d’inactivité à partir duquel le compteur n’enregistre plus.
Limite de temps : Permet d’arrêter le compteur lorsque ce temps est atteint.
Compte à rebours : Si une limite de temps est définie, le compteur se décrémente au lieu de s’incrémenter.
Heures:Minutes : 2:30
Heures:Minutes:Secondes : 2:30:02
Total Minutes : 150
Total Heures : 2.5
Le code généré par le script se trouve dans un noeud Python d’un tag Xpresso, ce qui permet de récupérer facilement la sortie pour la connecter avec ce que l’on veut. Par défaut la sortie est connectée avec le nom de l’objet neutre pour voir le temps dans le gestionnaire d’objet ou pour l’ajouter à l’HUD.
http://www.xsyann.com/fc4d/pointeusey_hud.png
Exemple avec une spline Texte :
http://www.xsyann.com/fc4d/pointeusey_xpresso.png
http://www.xsyann.com/fc4d/pointeusey_extrude.png
La petite particularité est que tout est généré à partir d’un script, ce qui permet de ne pas dépendre d’un fichier c4d (comme la plupart des presets Xpresso). Le script créé l’objet neutre avec ses données utilisateur puis le tag Xpresso et le noeud Python avec son code dedans.
Voici le code :
import c4d
ID_OPERATOR_PYTHON = 1022471
_display_modes = ["DISPLAY_H", "DISPLAY_M", "DISPLAY_HM", "DISPLAY_HMS"]
NODE_CODE = """import c4d
from datetime import datetime, timedelta
import re
CONTAINER_ID = 1033688
ELAPSED_SEC = 100
ELAPSED_MICRO = 101
__ENUM_IDS__
_languages = ['fr', 'us']
_strings = {
# User Data
UD_HIDE: {'us':"Hide", 'fr':"Masquer"},
UD_VALUE: {'us':"Value", 'fr':"Valeur"},
UD_RESET: {'us':"Reset", 'fr':"Remise à zéro"},
UD_IDLE: {'us':"Idle", 'fr':"Inactivité"},
UD_TIME_LIMIT: {'us':"Time limit", 'fr':"Limite de temps"},
UD_COUNTDOWN: {'us':"Countdown", 'fr':"Compte à rebours"},
UD_DISPLAY: {'us':"Display", 'fr':"Affichage"},
# Cycles
(UD_DISPLAY, DISPLAY_H): {'us':"Total Hours", 'fr': "Total Heures"},
(UD_DISPLAY, DISPLAY_M): {'us':"Total Minutes", 'fr': "Total Minutes"},
(UD_DISPLAY, DISPLAY_HM): {'us':"Hours:Minutes", 'fr': "Heures:Minutes"},
(UD_DISPLAY, DISPLAY_HMS): {'us':"Hours:Minutes:Seconds", 'fr': "Heures:Minutes:Secondes"},
# Strings
'Show': {'us':"Show", 'fr': "Afficher"},
'Hide': {'us':"Hide", 'fr':"Masquer"},
'Finished': {'us':"Finished", 'fr':"Terminé"},
}
def get_default_language():
i = 0
while True:
lang = c4d.GeGetLanguage(i)
if lang is None:
break
if lang["default_language"]:
lang = lang["extensions"].lower()
return lang if lang in _languages else 'us'
i += 1
def tr(s):
lang = get_default_language().lower()
if s in _strings:
return _strings[s][lang]
return s
def translate_ud(obj, lang):
for desc, bc in obj.GetUserDataContainer():
if not desc[1].id in _strings:
continue
name = _strings[desc[1].id][lang]
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = name
bc_cycle = bc[c4d.DESC_CYCLE]
if bc_cycle:
for k, v in bc_cycle:
bc_cycle[k] = _strings[(desc[1].id, k)][lang]
bc.SetContainer(c4d.DESC_CYCLE, bc_cycle)
obj.SetUserDataContainer(desc, bc)
_date = None
_total = None
_lang = None
class Duration(timedelta):
@staticmethod
def parse(s=""):
\"""Create timedelta from string.
\"""
regex = r'((?P<hours>\d+):)?((?P<minutes>\d+):?)(?P<seconds>\d+)?'
match_object = re.match(regex, str(s).replace(" ", ""))
if match_object is None:
return Duration()
args = dict((k, int(v)) for k, v in match_object.groupdict(default=0).items())
return Duration(**args)
def __add__(self, x):
y = super(Duration, self).__add__(x)
return Duration(days=y.days, seconds=y.seconds, microseconds=y.microseconds)
def __sub__(self, x):
y = super(Duration, self).__sub__(x)
return Duration(days=y.days, seconds=y.seconds, microseconds=y.microseconds)
def __str__(self):
return self.fmt("{th} : {m} : {s}")
def total_seconds(self, cast=int):
\"""Total seconds from timedelta.
\"""
return (self.microseconds + (self.seconds + self.days * 24 * 3600) * 10 ** 6) / cast(10 ** 6)
def fmt(self, fmt):
\"""String format.
\"""
seconds = self.total_seconds()
d = {'d': self.days}
d['h'], rem = divmod(self.seconds, 3600)
d['m'], d['s'] = divmod(rem, 60)
d['m'] = "{0:02d}".format(d['m'])
d['s'] = "{0:02d}".format(d['s'])
d['th'], d['tm'], d['ts'] = seconds / 3600, seconds / 60, seconds
d['thf'] = "{0:.1f}".format(seconds / 3600.0)
return fmt.format(**d)
def reset(default=Duration()):
global _date
global _total
_total = default
_date = datetime.now()
return default
def get_container(obj, container_id):
bc = obj[container_id]
if not bc:
bc = c4d.BaseContainer()
obj[container_id] = bc
return bc
def init(doc, controller, value):
\"""Init previous date and total elapsed time.
\"""
global _total
global _lang
if _lang is None:
container = get_container(doc, CONTAINER_ID)
_lang = get_default_language().lower()
translate_ud(controller, _lang)
if _total is None:
reset(value)
container = get_container(doc, CONTAINER_ID)
sec, micro = container[ELAPSED_SEC], container[ELAPSED_MICRO]
if sec is not None and micro is not None:
_total = Duration(seconds=sec, microseconds=micro)
elif str(_total) != str(value):
reset(value)
def get_delta():
\"""Return elapsed time from last execution.
\"""
global _date
now = datetime.now()
delta = now - _date
_date = now
return delta
def update(delta, idle, doc, controller):
\"""Update total and ouput.
\"""
global _total
if delta < idle or idle.total_seconds() == 0:
_total += delta
set_ud(controller, UD_VALUE, str(_total))
container = get_container(doc, CONTAINER_ID)
container[ELAPSED_SEC] = _total.total_seconds()
container[ELAPSED_MICRO] = _total.microseconds
doc.GetDataInstance().SetContainer(CONTAINER_ID, container)
def format_time(time_limit, display, countdown):
\"""Format output string.
\"""
global _total
formatted = ""
if _total >= time_limit and time_limit.total_seconds() != 0:
formatted = tr("Finished")
else:
total = _total
if countdown and time_limit.total_seconds() != 0:
total = time_limit - total
fmts = {DISPLAY_M: "{tm}", DISPLAY_H: "{thf}", DISPLAY_HM: "{th}:{m}", DISPLAY_HMS:"{th}:{m}:{s}"}
formatted = total.fmt(fmts[display])
return formatted
def get_ud(op, id_ud):
return op[c4d.ID_USERDATA, id_ud]
def set_ud(op, id_ud, value):
op[c4d.ID_USERDATA, id_ud] = value
def create_layer(obj, name):
layer = c4d.documents.LayerObject()
layer.SetName(name)
layer_root = doc.GetLayerObjectRoot()
layer.InsertUnder(layer_root)
obj.SetLayerObject(layer)
return layer
def hide(doc, obj):
layer = obj.GetLayerObject(doc)
if layer is None:
layer = create_layer(obj, "PointeuseY")
data = layer.GetLayerData(doc)
# Show / Hide Layer
data['manager'] = not data['manager']
layer.SetLayerData(doc, data)
# Switch button name
ud_bc = obj.GetUserDataContainer()
hide_bc, hide_desc = dict((desc[1].id, (bc, desc)) for desc, bc in ud_bc)[UD_HIDE]
names = [tr("Show"), tr("Hide")]
hide_bc[c4d.DESC_NAME] = names[data['manager']]
hide_bc[c4d.DESC_SHORT_NAME] = names[data['manager']]
obj.SetUserDataContainer(hide_desc, hide_bc)
def main():
global __OUTPUT__ # Output Node
controller = op.GetNodeMaster().GetOwner().GetObject()
value = Duration.parse(get_ud(controller, UD_VALUE))
idle = Duration.parse(get_ud(controller, UD_IDLE))
time_limit = Duration.parse(get_ud(controller, UD_TIME_LIMIT))
set_ud(controller, UD_IDLE, str(idle))
set_ud(controller, UD_TIME_LIMIT, str(time_limit))
countdown = get_ud(controller, UD_COUNTDOWN)
display = get_ud(controller, UD_DISPLAY)
if get_ud(controller, UD_RESET):
value = reset()
set_ud(controller, UD_RESET, False)
if get_ud(controller, UD_HIDE):
hide(doc, controller)
set_ud(controller, UD_HIDE, False)
init(doc, controller, value)
delta = get_delta()
update(delta, idle, doc, controller)
__OUTPUT__ = format_time(time_limit, display, countdown)
"""
def create_UD_container(obj, dtype, name, parent):
bc = c4d.GetCustomDataTypeDefault(dtype)
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = name
bc[c4d.DESC_PARENTGROUP] = parent
return bc
def create_UD_default(obj, bc, default):
bc[c4d.DESC_DEFAULT] = default
ud = obj.AddUserData(bc)
obj[ud] = default
return ud
def create_UD_group(obj, name, parent=None):
bc = create_UD_container(obj, c4d.DTYPE_GROUP, name, parent)
return obj.AddUserData(bc)
def create_UD_string(obj, name, parent=None, default=""):
bc = create_UD_container(obj, c4d.DTYPE_STRING, name, parent)
return create_UD_default(obj, bc, default)
def create_UD_bool(obj, name, parent=None, default=False, gui=c4d.CUSTOMGUI_BOOL):
bc = create_UD_container(obj, c4d.DTYPE_BOOL, name, parent)
bc[c4d.DESC_CUSTOMGUI] = gui
return create_UD_default(obj, bc, default)
def create_UD_cycle(obj, name, parent=None, default=0, populate={}):
bc = create_UD_container(obj, c4d.DTYPE_LONG, name, parent)
bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_CYCLE
items = c4d.BaseContainer()
for i, item in populate.iteritems():
items.SetString(i, item)
bc[c4d.DESC_CYCLE] = items
return create_UD_default(obj, bc, default)
def create_userdata(null):
group = create_UD_group(null, "PointeuseY", c4d.DescID(0))
ud_ids = {}
ud_ids["UD_VALUE"] = create_UD_string(null, "", group, "0:00:00")[1].id
ud_ids["UD_RESET"] = create_UD_bool(null, "", group, gui=c4d.CUSTOMGUI_BUTTON)[1].id
ud_ids["UD_IDLE"] = create_UD_string(null, "", group, "0:05:00")[1].id
ud_ids["UD_TIME_LIMIT"] = create_UD_string(null, "", group, "3:00:00")[1].id
ud_ids["UD_COUNTDOWN"] = create_UD_bool(null, "", group)[1].id
items = dict((i, "dummy") for i, mode in enumerate(_display_modes))
ud_ids["UD_DISPLAY"] = create_UD_cycle(null, "", group, populate=items, default=3)[1].id
ud_ids["UD_HIDE"] = create_UD_bool(null, "", group, gui=c4d.CUSTOMGUI_BUTTON)[1].id
return ud_ids
def create_xpresso(null, ud_ids):
xpresso = c4d.BaseTag(c4d.Texpresso)
null.InsertTag(xpresso)
master = xpresso.GetNodeMaster()
python_node = master.CreateNode(master.GetRoot(), ID_OPERATOR_PYTHON, x=10, y=100)
formatted_port = python_node.AddPort(c4d.GV_PORT_OUTPUT, c4d.OUT_STRING, message=True)
python_node[c4d.GV_PYTHON_CODE] = generate_code(ud_ids, formatted_port.GetName(python_node))
null_node = master.CreateNode(master.GetRoot(), c4d.ID_OPERATOR_OBJECT, x=300, y=100)
null_node[c4d.GV_OBJECT_OBJECT_ID] = null
name_port = null_node.AddPort(c4d.GV_PORT_INPUT, c4d.ID_BASELIST_NAME)
name_port.Connect(formatted_port)
python_node.RemoveUnusedPorts()
def generate_code(ud_ids, output_name):
enum_ids = ""
for i, mode in enumerate(_display_modes):
enum_ids += "{0} = {1}\n".format(mode, i)
for k, v in ud_ids.iteritems():
enum_ids += "{0} = {1}\n".format(k, v)
return NODE_CODE.replace("__ENUM_IDS__", enum_ids).replace("__OUTPUT__", output_name)
def create_object(doc, object_type):
obj = c4d.BaseObject(object_type)
doc.InsertObject(obj)
doc.AddUndo(c4d.UNDO_NEW, obj)
doc.SetActiveObject(obj)
return obj
def main():
null = create_object(doc, c4d.Onull)
ud_ids = create_userdata(null)
create_xpresso(null, ud_ids)
c4d.EventAdd(c4d.EVENT_0)
if __name__=='__main__':
main()
http://xsyann.com/fc4d/PointeuseY.py
edit : J'avais oublié que Val l'avait déjà fais aussi, si vous voulez un chrono en mode plugin avec l'utilisation d'un vrai timer c'est ici : http://frenchcinema4d.fr/showthread.php?74574-Py-Timer
Je vous partage un petit exercice Python que j’ai fait, qui consiste à recoder La PointeuseX™ de Jean-Laurent en Python.
http://frenchcinema4d.fr/showthread.php?57408-Compteur-temps-pass%E9
Le principe de Jean-Laurent était de comparer à chaque exécution la minute courante avec celle de l’exécution précédente et en cas de différence (une ou plusieurs minutes écoulées), ajouter cette différence au compteur.
Le principe que j’ai utilisé est de calculer le temps écoulé entre chaque exécution (aussi court soit-il) et de l’ajouter au compteur.
http://www.xsyann.com/fc4d/pointeusey_gui.png
Valeur : La valeur courante du compteur (il est possible de la modifier manuellement).
Inactivité : Temps d’inactivité à partir duquel le compteur n’enregistre plus.
Limite de temps : Permet d’arrêter le compteur lorsque ce temps est atteint.
Compte à rebours : Si une limite de temps est définie, le compteur se décrémente au lieu de s’incrémenter.
Heures:Minutes : 2:30
Heures:Minutes:Secondes : 2:30:02
Total Minutes : 150
Total Heures : 2.5
Le code généré par le script se trouve dans un noeud Python d’un tag Xpresso, ce qui permet de récupérer facilement la sortie pour la connecter avec ce que l’on veut. Par défaut la sortie est connectée avec le nom de l’objet neutre pour voir le temps dans le gestionnaire d’objet ou pour l’ajouter à l’HUD.
http://www.xsyann.com/fc4d/pointeusey_hud.png
Exemple avec une spline Texte :
http://www.xsyann.com/fc4d/pointeusey_xpresso.png
http://www.xsyann.com/fc4d/pointeusey_extrude.png
La petite particularité est que tout est généré à partir d’un script, ce qui permet de ne pas dépendre d’un fichier c4d (comme la plupart des presets Xpresso). Le script créé l’objet neutre avec ses données utilisateur puis le tag Xpresso et le noeud Python avec son code dedans.
Voici le code :
import c4d
ID_OPERATOR_PYTHON = 1022471
_display_modes = ["DISPLAY_H", "DISPLAY_M", "DISPLAY_HM", "DISPLAY_HMS"]
NODE_CODE = """import c4d
from datetime import datetime, timedelta
import re
CONTAINER_ID = 1033688
ELAPSED_SEC = 100
ELAPSED_MICRO = 101
__ENUM_IDS__
_languages = ['fr', 'us']
_strings = {
# User Data
UD_HIDE: {'us':"Hide", 'fr':"Masquer"},
UD_VALUE: {'us':"Value", 'fr':"Valeur"},
UD_RESET: {'us':"Reset", 'fr':"Remise à zéro"},
UD_IDLE: {'us':"Idle", 'fr':"Inactivité"},
UD_TIME_LIMIT: {'us':"Time limit", 'fr':"Limite de temps"},
UD_COUNTDOWN: {'us':"Countdown", 'fr':"Compte à rebours"},
UD_DISPLAY: {'us':"Display", 'fr':"Affichage"},
# Cycles
(UD_DISPLAY, DISPLAY_H): {'us':"Total Hours", 'fr': "Total Heures"},
(UD_DISPLAY, DISPLAY_M): {'us':"Total Minutes", 'fr': "Total Minutes"},
(UD_DISPLAY, DISPLAY_HM): {'us':"Hours:Minutes", 'fr': "Heures:Minutes"},
(UD_DISPLAY, DISPLAY_HMS): {'us':"Hours:Minutes:Seconds", 'fr': "Heures:Minutes:Secondes"},
# Strings
'Show': {'us':"Show", 'fr': "Afficher"},
'Hide': {'us':"Hide", 'fr':"Masquer"},
'Finished': {'us':"Finished", 'fr':"Terminé"},
}
def get_default_language():
i = 0
while True:
lang = c4d.GeGetLanguage(i)
if lang is None:
break
if lang["default_language"]:
lang = lang["extensions"].lower()
return lang if lang in _languages else 'us'
i += 1
def tr(s):
lang = get_default_language().lower()
if s in _strings:
return _strings[s][lang]
return s
def translate_ud(obj, lang):
for desc, bc in obj.GetUserDataContainer():
if not desc[1].id in _strings:
continue
name = _strings[desc[1].id][lang]
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = name
bc_cycle = bc[c4d.DESC_CYCLE]
if bc_cycle:
for k, v in bc_cycle:
bc_cycle[k] = _strings[(desc[1].id, k)][lang]
bc.SetContainer(c4d.DESC_CYCLE, bc_cycle)
obj.SetUserDataContainer(desc, bc)
_date = None
_total = None
_lang = None
class Duration(timedelta):
@staticmethod
def parse(s=""):
\"""Create timedelta from string.
\"""
regex = r'((?P<hours>\d+):)?((?P<minutes>\d+):?)(?P<seconds>\d+)?'
match_object = re.match(regex, str(s).replace(" ", ""))
if match_object is None:
return Duration()
args = dict((k, int(v)) for k, v in match_object.groupdict(default=0).items())
return Duration(**args)
def __add__(self, x):
y = super(Duration, self).__add__(x)
return Duration(days=y.days, seconds=y.seconds, microseconds=y.microseconds)
def __sub__(self, x):
y = super(Duration, self).__sub__(x)
return Duration(days=y.days, seconds=y.seconds, microseconds=y.microseconds)
def __str__(self):
return self.fmt("{th} : {m} : {s}")
def total_seconds(self, cast=int):
\"""Total seconds from timedelta.
\"""
return (self.microseconds + (self.seconds + self.days * 24 * 3600) * 10 ** 6) / cast(10 ** 6)
def fmt(self, fmt):
\"""String format.
\"""
seconds = self.total_seconds()
d = {'d': self.days}
d['h'], rem = divmod(self.seconds, 3600)
d['m'], d['s'] = divmod(rem, 60)
d['m'] = "{0:02d}".format(d['m'])
d['s'] = "{0:02d}".format(d['s'])
d['th'], d['tm'], d['ts'] = seconds / 3600, seconds / 60, seconds
d['thf'] = "{0:.1f}".format(seconds / 3600.0)
return fmt.format(**d)
def reset(default=Duration()):
global _date
global _total
_total = default
_date = datetime.now()
return default
def get_container(obj, container_id):
bc = obj[container_id]
if not bc:
bc = c4d.BaseContainer()
obj[container_id] = bc
return bc
def init(doc, controller, value):
\"""Init previous date and total elapsed time.
\"""
global _total
global _lang
if _lang is None:
container = get_container(doc, CONTAINER_ID)
_lang = get_default_language().lower()
translate_ud(controller, _lang)
if _total is None:
reset(value)
container = get_container(doc, CONTAINER_ID)
sec, micro = container[ELAPSED_SEC], container[ELAPSED_MICRO]
if sec is not None and micro is not None:
_total = Duration(seconds=sec, microseconds=micro)
elif str(_total) != str(value):
reset(value)
def get_delta():
\"""Return elapsed time from last execution.
\"""
global _date
now = datetime.now()
delta = now - _date
_date = now
return delta
def update(delta, idle, doc, controller):
\"""Update total and ouput.
\"""
global _total
if delta < idle or idle.total_seconds() == 0:
_total += delta
set_ud(controller, UD_VALUE, str(_total))
container = get_container(doc, CONTAINER_ID)
container[ELAPSED_SEC] = _total.total_seconds()
container[ELAPSED_MICRO] = _total.microseconds
doc.GetDataInstance().SetContainer(CONTAINER_ID, container)
def format_time(time_limit, display, countdown):
\"""Format output string.
\"""
global _total
formatted = ""
if _total >= time_limit and time_limit.total_seconds() != 0:
formatted = tr("Finished")
else:
total = _total
if countdown and time_limit.total_seconds() != 0:
total = time_limit - total
fmts = {DISPLAY_M: "{tm}", DISPLAY_H: "{thf}", DISPLAY_HM: "{th}:{m}", DISPLAY_HMS:"{th}:{m}:{s}"}
formatted = total.fmt(fmts[display])
return formatted
def get_ud(op, id_ud):
return op[c4d.ID_USERDATA, id_ud]
def set_ud(op, id_ud, value):
op[c4d.ID_USERDATA, id_ud] = value
def create_layer(obj, name):
layer = c4d.documents.LayerObject()
layer.SetName(name)
layer_root = doc.GetLayerObjectRoot()
layer.InsertUnder(layer_root)
obj.SetLayerObject(layer)
return layer
def hide(doc, obj):
layer = obj.GetLayerObject(doc)
if layer is None:
layer = create_layer(obj, "PointeuseY")
data = layer.GetLayerData(doc)
# Show / Hide Layer
data['manager'] = not data['manager']
layer.SetLayerData(doc, data)
# Switch button name
ud_bc = obj.GetUserDataContainer()
hide_bc, hide_desc = dict((desc[1].id, (bc, desc)) for desc, bc in ud_bc)[UD_HIDE]
names = [tr("Show"), tr("Hide")]
hide_bc[c4d.DESC_NAME] = names[data['manager']]
hide_bc[c4d.DESC_SHORT_NAME] = names[data['manager']]
obj.SetUserDataContainer(hide_desc, hide_bc)
def main():
global __OUTPUT__ # Output Node
controller = op.GetNodeMaster().GetOwner().GetObject()
value = Duration.parse(get_ud(controller, UD_VALUE))
idle = Duration.parse(get_ud(controller, UD_IDLE))
time_limit = Duration.parse(get_ud(controller, UD_TIME_LIMIT))
set_ud(controller, UD_IDLE, str(idle))
set_ud(controller, UD_TIME_LIMIT, str(time_limit))
countdown = get_ud(controller, UD_COUNTDOWN)
display = get_ud(controller, UD_DISPLAY)
if get_ud(controller, UD_RESET):
value = reset()
set_ud(controller, UD_RESET, False)
if get_ud(controller, UD_HIDE):
hide(doc, controller)
set_ud(controller, UD_HIDE, False)
init(doc, controller, value)
delta = get_delta()
update(delta, idle, doc, controller)
__OUTPUT__ = format_time(time_limit, display, countdown)
"""
def create_UD_container(obj, dtype, name, parent):
bc = c4d.GetCustomDataTypeDefault(dtype)
bc[c4d.DESC_NAME] = name
bc[c4d.DESC_SHORT_NAME] = name
bc[c4d.DESC_PARENTGROUP] = parent
return bc
def create_UD_default(obj, bc, default):
bc[c4d.DESC_DEFAULT] = default
ud = obj.AddUserData(bc)
obj[ud] = default
return ud
def create_UD_group(obj, name, parent=None):
bc = create_UD_container(obj, c4d.DTYPE_GROUP, name, parent)
return obj.AddUserData(bc)
def create_UD_string(obj, name, parent=None, default=""):
bc = create_UD_container(obj, c4d.DTYPE_STRING, name, parent)
return create_UD_default(obj, bc, default)
def create_UD_bool(obj, name, parent=None, default=False, gui=c4d.CUSTOMGUI_BOOL):
bc = create_UD_container(obj, c4d.DTYPE_BOOL, name, parent)
bc[c4d.DESC_CUSTOMGUI] = gui
return create_UD_default(obj, bc, default)
def create_UD_cycle(obj, name, parent=None, default=0, populate={}):
bc = create_UD_container(obj, c4d.DTYPE_LONG, name, parent)
bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_CYCLE
items = c4d.BaseContainer()
for i, item in populate.iteritems():
items.SetString(i, item)
bc[c4d.DESC_CYCLE] = items
return create_UD_default(obj, bc, default)
def create_userdata(null):
group = create_UD_group(null, "PointeuseY", c4d.DescID(0))
ud_ids = {}
ud_ids["UD_VALUE"] = create_UD_string(null, "", group, "0:00:00")[1].id
ud_ids["UD_RESET"] = create_UD_bool(null, "", group, gui=c4d.CUSTOMGUI_BUTTON)[1].id
ud_ids["UD_IDLE"] = create_UD_string(null, "", group, "0:05:00")[1].id
ud_ids["UD_TIME_LIMIT"] = create_UD_string(null, "", group, "3:00:00")[1].id
ud_ids["UD_COUNTDOWN"] = create_UD_bool(null, "", group)[1].id
items = dict((i, "dummy") for i, mode in enumerate(_display_modes))
ud_ids["UD_DISPLAY"] = create_UD_cycle(null, "", group, populate=items, default=3)[1].id
ud_ids["UD_HIDE"] = create_UD_bool(null, "", group, gui=c4d.CUSTOMGUI_BUTTON)[1].id
return ud_ids
def create_xpresso(null, ud_ids):
xpresso = c4d.BaseTag(c4d.Texpresso)
null.InsertTag(xpresso)
master = xpresso.GetNodeMaster()
python_node = master.CreateNode(master.GetRoot(), ID_OPERATOR_PYTHON, x=10, y=100)
formatted_port = python_node.AddPort(c4d.GV_PORT_OUTPUT, c4d.OUT_STRING, message=True)
python_node[c4d.GV_PYTHON_CODE] = generate_code(ud_ids, formatted_port.GetName(python_node))
null_node = master.CreateNode(master.GetRoot(), c4d.ID_OPERATOR_OBJECT, x=300, y=100)
null_node[c4d.GV_OBJECT_OBJECT_ID] = null
name_port = null_node.AddPort(c4d.GV_PORT_INPUT, c4d.ID_BASELIST_NAME)
name_port.Connect(formatted_port)
python_node.RemoveUnusedPorts()
def generate_code(ud_ids, output_name):
enum_ids = ""
for i, mode in enumerate(_display_modes):
enum_ids += "{0} = {1}\n".format(mode, i)
for k, v in ud_ids.iteritems():
enum_ids += "{0} = {1}\n".format(k, v)
return NODE_CODE.replace("__ENUM_IDS__", enum_ids).replace("__OUTPUT__", output_name)
def create_object(doc, object_type):
obj = c4d.BaseObject(object_type)
doc.InsertObject(obj)
doc.AddUndo(c4d.UNDO_NEW, obj)
doc.SetActiveObject(obj)
return obj
def main():
null = create_object(doc, c4d.Onull)
ud_ids = create_userdata(null)
create_xpresso(null, ud_ids)
c4d.EventAdd(c4d.EVENT_0)
if __name__=='__main__':
main()
http://xsyann.com/fc4d/PointeuseY.py
edit : J'avais oublié que Val l'avait déjà fais aussi, si vous voulez un chrono en mode plugin avec l'utilisation d'un vrai timer c'est ici : http://frenchcinema4d.fr/showthread.php?74574-Py-Timer