[Logiciel 2D] Animatoon

Programmation d'applications complexes
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

Spock a écrit :le plus simple, ce serai tout simplement, de prendre une capture d'ecran (de ton image resultat ) , apres chaque modification (a commencer par la premiere evidement )

(un buffer de capture ... donc une liste de captures)
qui permet lorsqu'on reviens en arriere, de remettre dans l'ecran du soft les captures listé en sens inverse a chaque Undo ...

non ? :)
ça pourrait fonctionner si je n'avais pas de calques et que je bossais sur des images de la taille maximum de mon écran, mais sur une image en 2048*2048 avec 10 calques, sauvegarder l'image de l'iamge (donc à 100%) m'oblige à la découper, à déplacer les calques, à sauvegarder chaque morceaux, puis à recréer l'image avec chacun des morceaux ^^.
C'est ce que je fais quand j'enregistre mon document en fusionnant tous les calques par exemple. Et ça prend à chaque fois plusieurs secondes. Je ne me vois pas bloquer le soft dès qu'on fait une modification ^^. En plus, avec cette technique, ça ne gère pas vraiment les changements via les calques.

Par contre, je pourrais sauver uniquement le calque (le sprite ou l'image) qui a été modifié à chaque fois que je relâche la souris, ça pourrait être une idée ;). Je vais y réfléchir, merci de la suggestion.
ps: tu peux meme eventuellement bosser sur fichiers ...pour eviter de bouffer trop de Ram.. les disques son rapides maintenant
Tu veux dire quoi par bosser sur fichiers ?
voir meme exploiter les fichiers de capture, pour creer une animation de la progression du dessin :)
ça se serait bien sympa, c'est clair ^^.
Mais sur des images pas trop grandes.
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: [Logiciel 2D] Animatoon

Message par G-Rom »

Pour le undo/redo c'est encore plus simple , mais implique une gestion du code dès le départ de l'application.
L'application possède des "états" , à chaque action , l'état est dupliqué , le nouvel état prend en compte l'action , quel quelle soit , l'état courant est l'application tel qu'on la vois.

grosso modo :
Structure State
... propriété de l'application
endstructure

structure Application
newlist state.State()
*currentState.state
endstructure

procedure copyState(*a.State,*b.State)
...
endprocedure

procedure changeState(*application.Application, *state.State)
...
endprocedure

un undo reviens un état en arrière , un redo en avant. l'application dois être conçu dès le départ pour.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

G-Rom a écrit :Pour le undo/redo c'est encore plus simple , mais implique une gestion du code dès le départ de l'application.
L'application possède des "états" , à chaque action , l'état est dupliqué , le nouvel état prend en compte l'action , quel quelle soit , l'état courant est l'application tel qu'on la vois.
C'est à peu près ce que je prévoyais.
Pour les images, je pensais sauvegarder (dans un répertoire temporaire) la modification du calque en court (ou des calques), à chaque nouvelle action.
Si je relâche la souris et que j'ai dessiné, je sauvegarde la nouvelle image. Par contre, si par exemple, je diminué la taille de mon image, je sauvegarde tous les calques à l'ancienne taille.

J'avais aussi pensé à copier en "interne", avec copyimage(), chaque changement, mais je pense que c'est mieux de sauvegarder sur le disque dur.
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: [Logiciel 2D] Animatoon

Message par G-Rom »

C'est un compromis à faire, si tu opte pour système d'état, rien ne t'empêche de tout sauvegardé les états sur le disque ( utile en cas de plantage ) en revanche ton application sera moins véloce , l'accès au disque est plus long , c'est un choix technique qui t'appartient , tu peu même faire en sorte que l'utilisateur règle se paramètre , par exemple , memoire vive à consommer avant écriture sur disque, nombre d'action maximum à sauver, etc...
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

salut

voici deux nouvelles vidéos, pour vous montrer l'avancement d'animatoon :
(désolé, pas encore de version à tester, car j'ai encore quelques bugs et il manque des choses)

https://www.youtube.com/watch?v=A2MbJt1VhEE

https://www.youtube.com/watch?v=0pcLPx3zNYI

Et un de mes derniers tests (outil symétrie et watercolor (+colormix)):
Image
Micheao
Messages : 533
Inscription : dim. 07/déc./2014 10:12
Localisation : Sud-Est

Re: [Logiciel 2D] Animatoon

Message par Micheao »

salut

Tu utilise quelle tablette ? c'est trop beau j'adore et merci pour les vidéos
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

j'utilise une "vieille" wacom graphire A5, mais ça fonctionne pas trop mal (même si des fois, elle bugue un peu).
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: [Logiciel 2D] Animatoon

Message par G-Rom »

La grande classe ^^
Bravo Blendman !
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

@Spock : merci ;) En fait, c'est grâce à un de tes conseils que j'ai recodé entièrement animatoon (à partir du 29 mai 2015) et que je l'ai continué ;). Tu m'avais parlé de dessiner avec des sprites sur le screen et je suis parti de là. J'ai testé et comme ça marchait super bien, j'ai décidé de tout reprendre avec cette technique.
Puis, j'ai continué et désormais, je dessine directement sur des sprites avec les images des brosses, et j'affiche ensuite ces sprites sur le screen et ça va assez vite.
Par contre, je conserve l'idée de dessiner directement sur le screen avec des sprites pour l'affichage si besoin ;).
Ah si on avait le RenderTotexture et qu'on pouvait dessiner directement des sprites sur une surface, ça irait 3 fois plus vite et je pourrais faire encore plus de choses :).

@G-rom : merci, tu m'as aussi pas mal aidé sur certaines parties de ce soft ;).
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: [Logiciel 2D] Animatoon

Message par venom »

En effet un très bel outil que tu code blendman. Félicitation et bon courage pour la suite. 8)

Après il faut savoir dessiner un minimum pour utilisé ça :wink: :D







@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

venom a écrit :Après il faut savoir dessiner un minimum pour utilisé ça :wink: :D
En fait, on peut aussi retoucher des images, car j'ai ajouté quelques fonctionnalités de retouches:
- Réglages : niveau, contraste/luminosité, balance des couleurs, couleur inversée, désaturation, posterise...
- recadrer, tailler l'image (enlever les pixels transparents), agrandir, réduire l'image
- filtre : flou, ajouter du bruit...
etc...

Sinon, voici encore quelques essais :

Image

(sur celle-ci, le trait a été réalisé dans une ancienne version d'animatoon (réalisé avec gamemaker)
Image

Image

Image

Image
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: [Logiciel 2D] Animatoon

Message par G-Rom »

Superbe, la grande classe , l'empereur de la tablette^^ ! :D
Micheao
Messages : 533
Inscription : dim. 07/déc./2014 10:12
Localisation : Sud-Est

Re: [Logiciel 2D] Animatoon

Message par Micheao »

je suis sur le Cul c'est trop beau
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

Merci ;)
Spock a écrit :l'effet gaufré du fond de feuille tu l'obtiens comment ?
on a vraiment l'impression d'etre sur du canson :)
pour le moment, j'utilise une technique assez simple :
- je peints sur un calque avec un mode "multiply", donc pour que ça fonctionne, il faut que derrière il y ait une texture de papier (ce qui le cas).

Dans l'idéal, j'aimerai mettre en mode overlay tout au -dessus la même texture, mais comme j'utilise les sprites, je n'ai pas réussi à créer un blendmode overlay.
Si on avait du rendertotexture et la possibilité de mettre un shader sur une surface/un sprite, je pense que ça serait possible.

Une autre technique serait d'utiliser une sorte de shaders normalmap au dessus et même de pouvoir dessiner en fonction de cette normalmap, mais là, je ne sais pas
si c'est possible sans le rendertotexture ou les shaders sur les sprites.
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [Logiciel 2D] Animatoon

Message par blendman »

Spock a écrit :je voulais savoir, (et tu l'a surement deja expliqué, mais j'ai du zaper )
pourquoi tu utilises la Lib Sprites comme calque , a la place de la Lib images ?

(ou j'ai peut etre pas tout compris ) :)
En fait, j'utilise les deux libs : sprite (pour l'affichage temporaire) et image (pour le dessin)
C'est toi qui m'avait conseillé les sprites car c'était très rapide et c'est vrai ;).


J'utilise la lib sprite uniquement pour l'affichage.

Lorsque je dessine sur l'écran :
- je conserve la position X et Y (j'utilise windowmouseX() et windowmouseY() car avec mouseX() et MouseY(), j'ai quelques soucis avec ma tablette graphique, au niveau vitesse, de plus, ça m'évite de capturer la souris dans l'écran ;))
- j'affiche le papier (dans mon exemple c'est #spfond) + les calques (les sprites) en dessous de mon calque courant : donc ça va très vite.
- je dessine les images de ma brosse, avec les opérations (rotations, scale, couleur, etc...) sur le sprite courant, puis, je l'affiche
- je dessine les images de ma brosse, avec les opérations (rotations, scale, couleur, etc...) sur mon image
- j'affiche les calques du dessus (les sprites).

L'idéal serait d'utiliser les threads pour : conserver la position X et Y de la souris, dessiner sur le sprite, dessiner sur l'image.
Dessiner l'image sur le sprite est long si c'est une image qui fait plus de 1024*768.
Par contre, dessiner des sprites sur l'écran est très rapide, donc on peut avoir beaucoup de calques d'afficher ^^.


Voilà le code de base (très simplifié ^^) pour mieux comprendre :

Code : Tout sélectionner

; Animatoon : exemple basique du code pour dessiner.

;{ enumeration
Enumeration ; menuitem
  #menu_Clear  
  #menu_LayerAdd
EndEnumeration
Enumeration ; gadgets
  #G_BrushSize
  #G_BrushAlpha
  #G_BrushColor
  
  #G_layerList
EndEnumeration
#SpFond = 0
#ImgBrushColor = 0
;}

;{ structure
Structure sBrush
  
  Size.w
  Alpha.a
  Scatter.w
  Rotation.w
  Color.i
  R.a
  G.a
  b.a
EndStructure
Global brush.sBrush 
With brush
  \size = 10
  \Alpha = 120
  \r = Random(255)
  \g = Random(255)
  \b = Random(255)
  \Color = RGBA(\r,\g,\b,\Alpha)
EndWith
Structure sLayer
  
  Alpha.a
  View.a
  Bm.a
  
  Position.a 
  Image.i
  ImageAlpha.i
  Sprite.i
  Gadget.i
    
  X.w
  y.w
  Nom$
  W.w
  H.w
  
EndStructure
Global Dim layer.sLayer(0)
;}

Global doc_w,doc_h,layerId,NewPainting,canvasX,canvasY,Zoom.w
doc_w = 1024
doc_h = 768
Zoom = 100

;{ procedures
Procedure Layer_Add()
  
  n =ArraySize(layer())
  
  With layer(n)
    \Alpha  = 255
    \view   = 1  
    \Position = n
    \Nom$ = "Layer"+Str(n)
    \Image      = CreateImage(#PB_Any, doc_w, doc_h, 32,#PB_Image_Transparent)
    \ImageAlpha = CreateImage(#PB_Any, doc_w, doc_h, 32,#PB_Image_Transparent)
    \Sprite     = CreateSprite(#PB_Any, doc_w,doc_h,#PB_Sprite_AlphaBlending)
    If StartDrawing(SpriteOutput(\Sprite)) ; on efface le sprite
      DrawingMode(#PB_2DDrawing_AllChannels)
      Box(0,0,doc_w,doc_h,RGBA(0,0,0,0))
      StopDrawing()
    EndIf
    
    layerId = n
  EndWith
  
  ClearGadgetItems(#G_layerList)
  For i =0 To n
    AddGadgetItem(#G_layerList,i,layer(i)\Nom$)
  Next i
      
  ReDim layer(n+1)
  
EndProcedure
Procedure Layer_Draw(i)
  
  z.d =Zoom *0.01
  
  Select layer(i)\Bm
      
    Case 0
      SpriteBlendingMode(#PB_Sprite_BlendSourceAlpha, #PB_Sprite_BlendInvertSourceAlpha)
            
    Case 1 ; multiply
      SpriteBlendingMode(4,0)
      
    Case 2 ; Add
      SpriteBlendingMode(3,1)
      
  EndSelect
  
  ZoomSprite(layer(i)\Sprite,z*ImageWidth(layer(i)\Image),z*ImageHeight(layer(i)\Image))
  DisplayTransparentSprite(layer(i)\Sprite,layer(i)\x+canvasX,layer(i)\y+canvasY,layer(i)\Alpha)
  SpriteBlendingMode(#PB_Sprite_BlendSourceAlpha, #PB_Sprite_BlendInvertSourceAlpha)
  
EndProcedure
Procedure Layer_Update(i)
  
  
EndProcedure
Procedure ScreenUpdate()
  
  If NewPainting
    If StartDrawing(SpriteOutput(Layer(layerId)\Sprite)) ; on efface le sprite
      DrawingMode(#PB_2DDrawing_AllChannels)
      Box(0,0,doc_w,doc_h,RGBA(0,0,0,0))
      DrawAlphaImage(ImageID(layer(layerid)\Image),0,0)
      StopDrawing()
    EndIf
    NewPainting = 0
  EndIf
  
  ClearScreen(RGB(120,120,120))
  DisplayTransparentSprite(#SpFond,canvasX,canvasY)
  For i= 0 To ArraySize(layer())-1
    Layer_draw(i)
  Next i 
  FlipBuffers()
EndProcedure
Procedure UpdateColorPreview()
  If StartDrawing(ImageOutput(#ImgBrushColor))
    Box(0,0,OutputWidth(),OutputHeight(),RGB(brush\R,brush\G,brush\B))
    StopDrawing()
  EndIf 
  SetGadgetState(#G_BrushColor,ImageID(#ImgBrushColor))
EndProcedure
;}

;{ openwindow
screenwidth = 1200
screenheight = 768
OpenWindow(0, 0, 0, screenwidth, screenheight, "Animatoon base", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_MaximizeGadget)

InitSprite()
ScreenX = 100
ScreenY = 0
If OpenWindowedScreen(WindowID(0),ScreenX,ScreenY,screenwidth-ScreenX-100, screenheight)=0
  MessageRequester("Error", "Can't Open Screen!", 0)
  End
EndIf

;{ menu
If CreateMenu(0,WindowID(0))  
  MenuTitle("Editions")
  MenuItem(#Menu_Clear,"Effacer")  
  MenuTitle("Calques")
  MenuItem(#Menu_LayerAdd,"Ajouter calque")  
EndIf

;}

;{ gadgets
If PanelGadget(#PB_Any,0,0,ScreenX-5,WindowHeight(0))
  x = 10
  y = 10
  SpinGadget(#G_BrushSize,x,y,50,20,1,500,#PB_Spin_Numeric):y+25
  GadgetToolTip(#G_BrushSize,"Taille de la brosse")
  SetGadgetState(#G_BrushSize,brush\Size)
  SpinGadget(#G_BrushAlpha,x,y,50,20,0,255,#PB_Spin_Numeric):y+25
  GadgetToolTip(#G_BrushAlpha,"Opacité de la brosse")
  SetGadgetState(#G_BrushAlpha,brush\Alpha)
  If CreateImage(#ImgBrushColor,64,64)
    UpdateColorPreview()
  EndIf  
  ImageGadget(#G_BrushColor,x,y,64,64,ImageID(#ImgBrushColor))
  CloseGadgetList()
EndIf

If PanelGadget(#PB_Any,WindowWidth(0)-95,0,105,WindowHeight(0))
  x = 10
  y = 10
  ListViewGadget(#G_layerList,x,y,80,100)
  CloseGadgetList()
EndIf
;}

;{ autre 
If CreateSprite(#SpFond,Doc_w,doc_h,#PB_Sprite_AlphaBlending)
  If StartDrawing(SpriteOutput(#SpFond))
    DrawingMode(#PB_2DDrawing_AllChannels)
    Box(0,0,doc_w,doc_h,RGBA(160,160,160,255))
    StopDrawing()
  EndIf
EndIf
Layer_Add()
ScreenUpdate()
;}

;}

Repeat
  
  mx = WindowMouseX(0) - ScreenX
  my = WindowMouseY(0) - ScreenY
  
  Repeat
    
    Event       = WaitWindowEvent(1)
    EventGadget = EventGadget()
    
    Select event
        
      Case #PB_Event_Gadget
          
        Select EventGadget
          Case #G_layerList
            LayerId =GetGadgetState(#G_layerList)
  
          Case #G_BrushSize
            brush\Size = GetGadgetState(#G_BrushSize)
            
          Case #G_BrushAlpha
            brush\Alpha = GetGadgetState(#G_BrushAlpha)
            brush\color =RGBA(brush\r,brush\g,brush\b,brush\Alpha)
            
          Case #G_BrushColor 
            If EventType() = #PB_EventType_LeftDoubleClick
              col = ColorRequester(brush\color)
              brush\r = Red(Col)
              brush\g = Green(Col)
              brush\b = Blue(Col)
              brush\color =RGBA(brush\r,brush\g,brush\b,brush\Alpha)
              UpdateColorPreview()
            EndIf
          
        EndSelect
        
      Case #PB_Event_Menu
        
        Select EventMenu()
            
          Case #menu_Clear
            If StartDrawing(ImageOutput(Layer(layerId)\Image)) ; on efface le sprite
              DrawingMode(#PB_2DDrawing_AllChannels)
              Box(0,0,doc_w,doc_h,RGBA(0,0,0,0))
              StopDrawing()
            EndIf
            NewPainting = 1 
            ScreenUpdate()
            
          Case #menu_LayerAdd
            Layer_Add()
            
        EndSelect
        
      Case #PB_Event_LeftClick ; mouse button up
        paint = 0
        
      Case #WM_LBUTTONDOWN ; mouse button down : pas d'équivalent event général
        If mx>=0 And my>=0 And mx<ScreenWidth() And my<ScreenHeight()
          paint = 1
        EndIf
        
      Case #PB_Event_CloseWindow
        End
        
    EndSelect
    
  Until event = 0 Or paint = 1
  
  If mx>=0 And my>=0 And mx<ScreenWidth() And my<ScreenHeight()
    
    If paint = 1
      ; on peint, j'update donc
      
      ClearScreen(RGB(120,120,120))
      DisplayTransparentSprite(#SpFond,canvasX,canvasY)
      For i= 0 To ArraySize(layer())-1
        If i< layerId
          Layer_draw(i)
        Else
          Break
        EndIf        
      Next i 
      
      ; je peins sur le sprite, attention c'est temporaire, uniquement pour l'affichage rapide.
      If StartDrawing(SpriteOutput(layer(layerid)\Sprite))
        DrawingMode(#PB_2DDrawing_AlphaBlend)
        xx = mx + Random(brush\Scatter)-Random(brush\Scatter)
        yy = my + Random(brush\Scatter)-Random(brush\Scatter)
        Circle(xx,yy,Brush\size,brush\color)
        
        StopDrawing()
      EndIf
                  
      ; puis je peins sur l'image, que je conserve      
      If StartDrawing(ImageOutput(layer(layerid)\Image))
        DrawingMode(#PB_2DDrawing_AlphaBlend)
        ;xx = mx - Brush\size + Random(brush\Scatter)-Random(brush\Scatter)
        ;yy = my - Brush\size + Random(brush\Scatter)-Random(brush\Scatter)
        Circle(xx,yy,Brush\size,brush\color)
        StopDrawing()
      EndIf
                  
       For i= layerId To ArraySize(layer())-1
         layer_draw(i)
       Next i 
       
      FlipBuffers()
    Else
            
    EndIf
    
  EndIf
  
  ; autre : keyboards par exemple
  
Until Event = #PB_Event_CloseWindow
Pour le moment, je n'ai pas encore travaillé sur l'optimisation du code, mais comme c'est encore assez fluide, je ferais ça plus tard ^^.
Répondre