; matrix anim plugin
; 2000 MARIN Laetitia 
; titix@amin.unice.fr
;
; version 0.1a Raymond Ostertag 2004/09
; - changed menu entry

(define (defilement count img original decalage intervalle)
  (if (> count 1)
      (begin 
	(let ((copy (car (gimp-layer-copy original TRUE))))
	  (gimp-image-add-layer img copy 0)
	  (gimp-layer-translate copy 0 decalage)
	  (defilement (- count 1) img original (+ decalage intervalle) intervalle)))))

(define (create-sequence img drawable color sens)
  (let* ((old-bg-color (car (gimp-palette-get-background)))
	 (old-fg-color (car (gimp-palette-get-foreground)))
	 (sizeX (car (gimp-image-width img)))
	 (sizeY (car (gimp-image-height img)))
	 (intervalle (/ sizeY 10))
	 (img2 (car (gimp-image-new sizeX (* sizeY 2) RGB)))	 
	 (n-layer1 (car (gimp-layer-new img2 sizeX (* sizeY 2) RGBA-IMAGE "copy" 100 NORMAL)))
	 (n-layer2 (car (gimp-layer-new img2 sizeX (* sizeY 2) RGBA-IMAGE "copy" 100 NORMAL)))
	 (background (car (gimp-layer-new img2 sizeX (* sizeY 2) RGBA-IMAGE "background" 100 NORMAL))))

    (gimp-image-add-layer img2 background 0)
    (gimp-image-add-layer img2 n-layer1 0)
    (gimp-image-add-layer img2 n-layer2 0)

    ;; init layers
    (gimp-palette-set-foreground color)
    (gimp-edit-fill background FG-IMAGE-FILL)
    (gimp-edit-clear n-layer1)	  	    
    (gimp-edit-clear n-layer2)

    ;; copy current image
    (gimp-selection-all img)
    (gimp-edit-copy drawable)

    ;;create double copy of image
    (let ((sel (car (gimp-edit-paste n-layer1 TRUE))))
      (gimp-floating-sel-anchor sel)
      (gimp-layer-translate n-layer1 0 (- 0 (/ sizeY 2))))
    
    (let ((sel (car (gimp-edit-paste n-layer2 TRUE))))
      (gimp-floating-sel-anchor sel)
      (gimp-layer-translate n-layer2 0 (+ 0 (/ sizeY 2))))

    ;; begin animation
    (let ((merged-layer (car (gimp-image-merge-visible-layers img2 1))))
      (if (= sens 0)
	  (gimp-layer-translate merged-layer 0 (- 0 (/ sizeY 2)))
	  (gimp-layer-translate merged-layer 0 (+ 0 (/ sizeY 2))))
      (gimp-selection-none img2)
      (gimp-edit-copy merged-layer)
      (if (= sens 0)
	  (defilement 10 img2 merged-layer intervalle intervalle)
	  (defilement 10 img2 merged-layer (- 0 intervalle) (- 0 intervalle))))

    ;; resize image
    (gimp-image-crop img2 sizeX sizeY 0 (/ sizeY 2))

    (gimp-selection-none img)
   
    (gimp-palette-set-foreground old-fg-color)
    (gimp-palette-set-background old-bg-color)

    img2))

(define (iterate-fn img matrix fn-size font i)
  (if (< i 19)
      (let* ((x (rand 11))
	     (y (if (> x 7) '" " (number->string x))))
	(if (<= x 7)
		(gimp-text-fontname img matrix (/ fn-size 3) (+ (/ fn-size 2) (* fn-size i)) y -1 TRUE fn-size 0 font))
	(iterate-fn img matrix fn-size font (+ i 1)))))

(define (create-column fore back fn-size font)
  (let* ((old-bg-color (car (gimp-palette-get-background)))
	 (old-fg-color (car (gimp-palette-get-foreground)))
	 (sizeX fn-size)
	 (sizeY (* fn-size 20))
	 (img (car (gimp-image-new sizeX sizeY RGB)))	 
	 (matrix (car (gimp-layer-new img sizeX sizeY RGBA-IMAGE "matrix" 100 NORMAL))))

    (gimp-palette-set-foreground fore)
    (gimp-palette-set-background back)
	 
    (gimp-image-add-layer img matrix 0)
    (gimp-edit-fill matrix BG-IMAGE-FILL)    
    
    (iterate-fn img matrix fn-size font 0)
    (gimp-floating-sel-anchor (car (gimp-image-get-floating-sel img)))
    (let ((img2 (create-sequence img matrix '(0 0 0) 0)))
      
      (gimp-palette-set-foreground old-fg-color)
      (gimp-palette-set-background old-bg-color)
      
      (gimp-image-delete img)
      img2)))


(define (merge img sizeX sizeY nb-layers img1 img2 layers-array1 layers-array2 decal)
  (if (> nb-layers 0)
      (begin 
	  ;; selection from img1
	  (gimp-selection-none img1)
	  (gimp-image-set-active-layer img1 (aref layers-array1 (- nb-layers 1)))
	  (gimp-edit-copy (aref layers-array1 (- nb-layers 1)))
	  (let ((merged-layer (car (gimp-layer-new img sizeX sizeY RGBA-IMAGE "merged-layer" 100 NORMAL))))
	    ;; new layer
	    (gimp-image-add-layer img merged-layer 0)
	    (gimp-edit-clear merged-layer)	  	    
	    (let ((sel (car (gimp-edit-paste merged-layer FALSE))))
	      (gimp-floating-sel-anchor sel)
	      (gimp-layer-translate merged-layer (- (/ decal 2) (/ sizeX 2)) 0)
	      (gimp-layer-resize merged-layer sizeX sizeY (- 0 (+ (- (/ decal 2) (/ sizeX 2)) decal)) 0)))	      
	    ;; selection from img2
	  (gimp-selection-none img2)
	  (gimp-image-set-active-layer img2 (aref layers-array2 (- nb-layers 1)))
	  (gimp-edit-copy (aref layers-array2 (- nb-layers 1)))
	  (let ((merged-layer (car (gimp-layer-new img sizeX sizeY RGBA-IMAGE "merged-layer" 100 NORMAL))))
	    ;; new layer
	    (gimp-image-add-layer img merged-layer 0)
	    (gimp-edit-clear merged-layer)	  	    
	    (let ((sel (car (gimp-edit-paste merged-layer FALSE))))
	      (gimp-floating-sel-anchor sel)
	      (gimp-layer-translate merged-layer (+ (- (/ decal 2) (/ sizeX 2)) decal) 0)
	      (gimp-layer-resize merged-layer sizeX sizeY (- 0 (- (/ decal 2) (/ sizeX 2))) 0)))
	  ;; next
	  (gimp-drawable-set-visible (car (gimp-image-merge-visible-layers img 1)) FALSE)
	  (merge img sizeX sizeY (- nb-layers 1) img1 img2 layers-array1 layers-array2 decal))))

(define (set-visible img nb-layers layers-array)
  (if (> nb-layers 0)
      (begin 
	  (gimp-drawable-set-visible (aref layers-array (- nb-layers 1)) TRUE)
	  (set-visible img (- nb-layers 1) layers-array))))
  
      
(define (create-anim-by-merge img1 img2)
  (let* ((old-bg-color (car (gimp-palette-get-background)))
	 (old-fg-color (car (gimp-palette-get-foreground)))
	 (sizeX1 (car (gimp-image-width img1)))
	 (sizeY1 (car (gimp-image-height img1)))
	 (sizeX2 (car (gimp-image-width img2)))
	 (sizeY2 (car (gimp-image-height img2)))
	 (sizeX (+ sizeX1 sizeX2))
	 (sizeY (if (> sizeY1 sizeY2) sizeY1 sizeY2))
	 (img (car (gimp-image-new sizeX sizeY RGB))))

    (let* ((layers1 (gimp-image-get-layers img1))
	   (nb-layers1 (car layers1))
	   (layers-array1 (cadr layers1))
	   (layers2 (gimp-image-get-layers img2))
	   (nb-layers2 (car layers2))
	   (layers-array2 (cadr layers2)))
      (merge img sizeX sizeY  (if (< nb-layers1 nb-layers2) nb-layers1 nb-layers2) img1 img2 layers-array1 layers-array2 sizeX1))

    (let* ((layers (gimp-image-get-layers img))
	   (nb-layers (car layers))
	   (layers-array (cadr layers)))
      (set-visible img nb-layers layers-array))

    (gimp-palette-set-foreground old-fg-color)
    (gimp-palette-set-background old-bg-color)

    img))

(define (script-fu-matrix fore back fn-size font)
  (let ((img1 (create-column fore back fn-size font))
	(img2 (create-column fore back fn-size font))
	(img3 (create-column fore back fn-size font))
	(img4 (create-column fore back fn-size font))
	(img5 (create-column fore back fn-size font))
	(img6 (create-column fore back fn-size font))
	(img7 (create-column fore back fn-size font))
	(img8 (create-column fore back fn-size font)))  
    (gimp-display-new 
     (create-anim-by-merge  
      (create-anim-by-merge 
       (create-anim-by-merge img1 img2)
       (create-anim-by-merge img3 img4))
      (create-anim-by-merge 
       (create-anim-by-merge img5 img6)
       (create-anim-by-merge img7 img8)))) 
    (gimp-image-delete img1)
    (gimp-image-delete img2)
    (gimp-image-delete img3)
    (gimp-image-delete img4)
    (gimp-image-delete img5)
    (gimp-image-delete img6)
    (gimp-image-delete img7)
    (gimp-image-delete img8)))

(script-fu-register "script-fu-matrix"
		    "<Image>/Animators/Matrix..."
		    "make a matrix animation"
		    "MARIN Laetitia"
		    "MARIN Laetitia"
		    "Jun 2001"
		    ""
		    SF-COLOR _"fore color to use"  '(0 255 0)
		    SF-COLOR _"back color to use"  '(0 0 0)
		    SF-ADJUSTMENT _"Font Size (pixels)" '(32 2 256 1 10 0 0)
		    SF-FONT _"Font" "-adobe-helvetica-bold-r-normal-*-30-*-*-*-p-*-*-*") 


