Boutique Cinema 4D
Affichage des résultats 1 à 8 sur 8

Discussion: Générateur non bloquant

  1. #1
    Gourou Avatar de César Vonc
    Date d'inscription
    avril 2006
    C4D version
    Autre
    OS
    Windows 10
    Messages
    2 483

    Générateur non bloquant

    Bonjour,

    Je cherche à créer un générateur qui ne bloque pas tout Cinema 4D pendant que le calcul de l'objet s'effectue, un peu comme le Booléen que l'on peut annuler avant qu'il termine son opération.

    Code PHP:
    class Essai(plugins.ObjectData):

        
    def __init__(self):
            
    self.SetOptimizeCache(True)

        
    def GetVirtualObjects(selfophierarchyhelp):
            
            for 
    i in xrange(5000000) :
                
    c4d.StatusSetBar(0.00002)
                
    math.sqrt(2*i)
            
            print 
    "Fini"
            
    c4d.StatusClear()
            
            return 
    c4d.BaseObject(c4d.Ocube)

    if 
    __name__ == "__main__":
        
    plugins.RegisterObjectPlugin(id=MODULE_IDstr="Essai",
                                    
    g=Essai,
                                    
    description="roundedtube"icon=None,
                                    
    info=c4d.OBJECT_GENERATOR
    Actuellement, on est obligé d'attendre que la boucle se termine, C4D ne veut rien entendre pendant.


    Alors j'ai lu dans la doc que la fonction GetVirtualObjects() était utilisée dans un fil d'exécution :
    This function is called in a thread context. Please see the important information about threading.
    Donc je commence à jouer avec la classe BaseThread :

    Code PHP:
    def GetVirtualObjects(selfophierarchyhelp):
            
            
    #c4d.StopAllThreads()
            
    fil c4d.threading.GeGetCurrentThread()
            
            for 
    i in xrange(5000000) :
                
    c4d.StatusSetBar(0.00002)
                
    math.sqrt(2*i)
                if 
    fil.TestBreak() :
                    print 
    "Coupe"
                    
    break
            
            print 
    "Fini"
            
    c4d.StatusClear()
            
            return 
    c4d.BaseObject(c4d.Ocube
    Sauf que maintenant, au moindre fait et geste, la boucle est interrompue. : P



    Je me demande s'il n'y a pas une solution plus sage, car les objets de type Déformateurs (c4d.OBJECT_MODIFIER) peuvent s'annuler d'office, sans qu'on ait rien à bidouiller dans le code. D'autant plus que la classe BaseThread est assez maigre en fonctions.
    Dernière modification par César Vonc ; 08/09/2013 à 11h57.

  2. #2
    Gourou Avatar de valkaari
    Date d'inscription
    mai 2009
    C4D version
    Autre
    OS
    OSX / windows
    Messages
    2 949
    si tu regardes l'exemple du roundtube en c++ il utilise le testBreak.

    Par contre il utiliser le HierarchyHelp fourni dans la fonction GetVirtualObject pour obtenir le thread avec un hh->GetThread()

    la fonction
    GeGetCurrentThread est à mon avis trop générique et ne renvoie pas le bon thread à tester.


    Le problème c'est que je sais pas si la fonction GetThread est dispo dans la classe HierarchyHelp en python.

    J'ai essayé une fois d'utiliser ça en c++ et ça coupé effectivement tout le temps.

    edit :
    essayes quand même avec un

    hierarchyhelp.GetThread()


    la fonction est peut être présente mais non documenté

    et en passant il faut aussi vérifier que le thread existe bien et qu'il n'a pas été "cassé"
    Dernière modification par valkaari ; 08/09/2013 à 18h12.

  3. #3
    Gourou Avatar de César Vonc
    Date d'inscription
    avril 2006
    C4D version
    Autre
    OS
    Windows 10
    Messages
    2 483
    Il ne semble y avoir hélas aucune fonction en Python dans le hierarchyhelper :

    AttributeError: 'PyCObject' object has no attribute 'GetThread'
    De même pour les autres fonctions (GetMg, GetDocument...), snif. J'ai essayé dans la démo de la R15, pour info.

    Je vais continuer de creuser la question.

  4. #4
    Pilier Avatar de paspas
    Date d'inscription
    février 2004
    Messages
    990
    salut

    une idée en passant :

    pourquoi ne pas utiliser une autre fonction pour ta boucle : la fonction while

    cette fonction est directement conditionnel

    une boucle du genre
    Code:
    while ( i < 50000) : 
        c4d.StatusSetBar(i * 0.00002)
        a = math.sqrt(2*i)
        if ( test == ta_condition) :
            i = 500001
         i = i+1
    des que la condition du while n'est plus respectée ta boucle s 'arrête

  5. #5
    Gourou Avatar de César Vonc
    Date d'inscription
    avril 2006
    C4D version
    Autre
    OS
    Windows 10
    Messages
    2 483
    Le soucis est que la condition à vérifier donnera toujours la même réponse étant donné que C4D restera figé tant que la boucle ne sera pas terminée.

    Il n'y a apparemment que la fonction TestBreak() qui permet de dire à C4D d'aller voir s'il n'y a pas d'évènement demandant l'arrêt du fil d'exécution.

    Sauf que comme l'a signalé Val, GeGetCurrentThread() est trop générique et ne renvoie probablement pas le fil dans lequel s'exécute la boucle.

  6. #6
    Gourou Avatar de valkaari
    Date d'inscription
    mai 2009
    C4D version
    Autre
    OS
    OSX / windows
    Messages
    2 949
    si tu trouves ça m’intéresse hein ^^ ou yann, qui traine dans le coin je t'ai vu !!!

  7. #7
    Gourou Avatar de César Vonc
    Date d'inscription
    avril 2006
    C4D version
    Autre
    OS
    Windows 10
    Messages
    2 483
    J'ai essayé avec C4DThread, en créant un nouveau fil contenant ma boucle, mais ce coup-ci, je n'arrive pas à l'arrêter avec un évènement extérieur car je ne trouve pas comment le détecter...

    La doc stipule pourtant qu'on peut vérifier si l'utilisateur a enfoncé la touche Échap :

    C4DThread.TestDBreak(self)
    Override this to add user breaks such as pressing ESC. This function is called by TestBreak().
    Mais rien n'est expliqué.

    On peut cependant utiliser un compteur dans TestDBreak, d'après Wilfried : http://www.plugincafe.com/forum/foru...ID=27325#27325
    Mais bon, je vois pas trop l'intérêt, on peut déjà vérifier le temps à chaque boucle sans même utiliser C4DThread. : /


    Voici néanmoins comment j'ai utilisé C4DThread, que rien ne semble pouvoir arrêter malgré le Wait(True) qui est censé couper en fonction des évènements C4D, si j'ai bien compris :


    Code PHP:
    import os
    import math
    import c4d

    from c4d import plugins
    utilsbitmaps
    from c4d
    .threading import C4DThread

    MODULE_ID 
    1000007

    class Fil(C4DThread):
        
        
    def TestDBreak(self) :
            
    #bc = c4d.BaseContainer()
            #print c4d.gui.GetInputEvent(c4d.BFM_INPUT_KEYBOARD, bc) # Marche pas :(
            
    print "ee"
            
    return False
        
        def Main
    (self):
            for 
    j in xrange(10) :
                if 
    self.TestBreak() :
                    print 
    "Coupe"
                    
    break
                
                for 
    i in xrange(500000) :
                    
    math.sqrt(2*i)
                        
                
    c4d.StatusSetBar(10)
            
    class 
    Essai(plugins.ObjectData):

        
    def __init__(self):
            
    self.SetOptimizeCache(True)
        
        
    def GetVirtualObjects(selfophh):
            
            
    Fil()
            
    f.Start(c4d.THREADMODE_ASYNCc4d.THREADPRIORITY_NORMAL)
            
            
    f.Wait(True)
            
    #f.End(True) Coupe directement
            
            
    c4d.StatusClear()
            print 
    "Fini"
            
    return c4d.BaseObject(c4d.Ocube)

    if 
    __name__ == "__main__":
        
    plugins.RegisterObjectPlugin(id=MODULE_IDstr="Essai",
                                    
    g=Essai,
                                    
    description="roundedtube"icon=None,
                                    
    info=c4d.OBJECT_GENERATOR
    Dernière modification par César Vonc ; 10/09/2013 à 14h12.

  8. #8
    Gourou Avatar de César Vonc
    Date d'inscription
    avril 2006
    C4D version
    Autre
    OS
    Windows 10
    Messages
    2 483
    Alors, j'ai trouvé une solution qui semble fonctionner, en utilisant la classe threading.Thread de Python plutôt que celle de C4D.

    Le calcul de l'objet s'effectue en parallèle et renvoie un neutre tant qu'il n'est pas terminé.
    Si le document est pour le rendu, le calcul de l'objet ne s'effectue pas en parallèle (self.fil.join() force l'attente).

    Il y a sûrement encore quelques petits détails à régler, je ne sais pas si ça plaît bien à C4D car on peut faire tout ce qu'on veut pendant que l'objet se calcule, ce qui implique pas mal de vérifications.

    Code PHP:
    import os
    import math
    import c4d
    import threading

    from c4d import plugins
    utilsbitmaps

    MODULE_ID 
    1000007

    class Fil(threading.Thread):
        
    op None
        resultat 
    None
        
        def __init__
    (selfop) :
            
    threading.Thread.__init__(self)
            
    self.op op
        
        def verif
    (self) :
            if 
    not self.op.IsAlive() : return True
            
    if not self.op.GetDocument() : return True
            
    if not self.op.GetDocument().IsAlive() : return True
            
    if not self.op[c4d.ID_BASEOBJECT_GENERATOR_FLAG] : return True
            
    return False
        
        def run
    (self) :
            print 
    "Commence calcul"
            
            
    for j in xrange(10) :
            
                if 
    self.verif() :
                    print 
    "Coupe"
                    
    return
                
                for 
    i in xrange(1000000) :
                    
    math.sqrt(2*i)
                        
                
    c4d.StatusSetBar(10)
            
            print 
    "Termine calcul"
            
    self.resultat c4d.BaseObject(c4d.Ocube)
            
    c4d.StatusClear()
            
    self.op.Touch()
            
    class 
    Essai(plugins.ObjectData):
        
    fil None
        
        def __init__
    (self):
            
    self.SetOptimizeCache(True)
        
        
    def GetVirtualObjects(selfophh):
            
            
    # Si le fil existe déjà, s'il a un résultat calculé, si ce résultat est utilisable
            
    if self.fil and self.fil.resultat and self.fil.resultat.IsAlive() :
                
    # Renvoie le résultat déjà calculé
                
    return self.fil.resultat
            
            
    else :
                
    # Si le fil existe déjà et s'il est en cours de calcul, renvoyer un neutre
                
    if self.fil and self.fil.isAlive() : return c4d.BaseObject(c4d.Onull)
                
                
    # Créé le nouveau fil et renvoie un neutre pendant le calcul
                
    self.fil Fil(op)
                
                
    self.fil.start()
                if (
    op.GetDocument() != c4d.documents.GetActiveDocument()) : # Si Rendu
                    
    self.fil.join() # Attendre que le calcul se termine et renvoyer le résultat
                    
    return self.fil.resultat
                
                
    return c4d.BaseObject(c4d.Onull)
            

    if 
    __name__ == "__main__":
        
    plugins.RegisterObjectPlugin(id=MODULE_IDstr="Essai",
                                    
    g=Essai,
                                    
    description="roundedtube"icon=None,
                                    
    info=c4d.OBJECT_GENERATOR

    Par ailleurs, j'ai voulu au début utiliser la classe multiprocessing de Python qui, d'après ce que j'ai compris, permet d'utiliser tous les processeurs à 100 %, mais pas moyen, j'ai une chiée d'erreurs « pickling » dont je ne comprends pas vraiment le sens.

Discussions similaires

  1. ivy generateur
    Par foubrun dans le forum Nouveaux membres
    Réponses: 7
    Dernier message: 09/07/2010, 07h59
  2. Générateur de rails
    Par arno dans le forum MoGraph
    Réponses: 4
    Dernier message: 13/06/2008, 09h42
  3. Génerateur de visage 3D
    Par sinclairzxfr dans le forum Compatibilité
    Réponses: 3
    Dernier message: 18/12/2005, 22h59
  4. Générateur de caustiques
    Par archeo dans le forum Textures
    Réponses: 3
    Dernier message: 07/08/2004, 01h30
  5. Générateur à Plasma !
    Par khadgar dans le forum Travaux en cours
    Réponses: 16
    Dernier message: 18/05/2004, 22h33

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •  
Mediaworks - Logiciels 3D | Design Internet - Creation site internet