;; generate knobs for reaktor (define (script-fu-reaktor-knob size width active-width steps scale-steps start-degree start-dent small-dent active-color inactive-color bg-color) (let* ((img (car (gimp-image-new size (* steps size) RGB))) (animation-layer (car (gimp-layer-new img size (* size steps) RGBA-IMAGE "Animation Layer" 100 NORMAL-MODE))) ; (bg-layer (car (gimp-layer-new img size size RGB-IMAGE ; "Background Layer" 100 NORMAL-MODE))) ;; (inactive-layer (car (gimp-layer-new img size size RGB-IMAGE ;; "Inactive Layer" 100 NORMAL-MODE))) ;; (active-layer (car (gimp-layer-new img size size RGB-IMAGE ;; "Active Layer" 100 NORMAL-MODE))) ) (gimp-context-push) ;; pushes a context to the top of the plug-in's contet stack (gimp-image-undo-disable img) ;; disables the image's undo stack (gimp-image-add-layer img animation-layer 0) ;; (gimp-image-add-layer image layer position) (gimp-edit-clear animation-layer) (gimp-context-set-background bg-color) ; (gimp-layer-set-preserve-trans animation-layer 1) (gimp-edit-fill animation-layer BACKGROUND-FILL) ;; fill background of layer (let* ((i 0) (radius (/ (- size (+ width 3)) 2)) (inactive-channel (make-circle-selection img size radius width scale-steps start-degree start-dent small-dent)) (active-channel (make-circle-selection img size radius active-width scale-steps start-degree start-dent small-dent)) (inc (/ 1 (- steps 1))) (pos 0)) (while (< i steps) (make-button img size bg-color inactive-color active-color inactive-channel active-channel i start-degree start-dent pos) (set! i (+ i 1)) (set! pos (+ pos inc)))) ;; (gimp-image-add-layer img inactive-layer 0) ;(let ((array (cons-array (* 3 2) 'double))) ; (aset array 0 32) ; (aset array 1 32) ; (aset array 2 0) ; (aset array 3 0) ; (aset array 4 64) ; (aset array 5 0) ; (gimp-free-select img 6 array CHANNEL-OP-SUBTRACT TRUE FALSE 0)) ;; (gimp-edit-bucket-fill drawable fill-mode paint-mode opacity threshold sample-merged x y) (gimp-selection-none img) (gimp-image-undo-enable img) (gimp-image-flatten img) (gimp-display-new img) (gimp-context-pop))) ;; (gimp-edit-blend img FG-BG-RGB-MODE NORMAL-MODE ;; GRADIENT-RADIAL 100 0 REPEAT-NONE FALSE ;; FALSE 0 0 TRUE (define (make-circle-selection img size radius width scale-steps start-degree start-dent small-dent) (let ((cx (/ size 2)) (cy (/ size 2))) (gimp-selection-none img) (let ((r (+ radius (/ width 2)))) (gimp-ellipse-select img (- cx r) (- cy r) (* 2 r) (* 2 r) CHANNEL-OP-REPLACE TRUE FALSE 0)) (let ((r (- radius (/ width 2)))) (gimp-ellipse-select img (- cx r) (- cy r) (* 2 r) (* 2 r) CHANNEL-OP-SUBTRACT TRUE FALSE 0)) ;; start dent (subtract-dent img size (deg-to-radian start-degree) (deg-to-radian start-dent)) ;; interval dents (let* ((i scale-steps) (step (/ (- 360 start-dent) scale-steps)) (offs (+ start-degree (/ start-dent 2) 0))) (while (>= i 0) (subtract-dent img size (deg-to-radian offs) (deg-to-radian small-dent)) (set! i (- i 1)) (set! offs (+ offs step)))) (car (gimp-selection-save img)))) (define (make-button img size bg-color inactive-color active-color inactive-channel active-channel step start-degree start-dent position) (let ((layer (car (gimp-layer-new img size size RGBA-IMAGE "Button Layer" 100 NORMAL-MODE)))) (gimp-image-add-layer img layer -1) (gimp-edit-clear layer) ; (gimp-layer-set-preserve-trans layer 1) (dented-circle img layer inactive-channel size inactive-color start-degree start-dent 1) (if (> position 0) (dented-circle img layer active-channel size active-color start-degree start-dent position)) (gimp-layer-translate layer 0 (* size step)))) ; (gimp-image-merge-visible-layers img CLIP-TO-IMAGE))) (define (dented-circle img layer channel size color start-degree start-dent length) (let ((cx (/ size 2)) (cy (/ size 2))) (gimp-selection-none img) (gimp-context-set-foreground color) (gimp-selection-load channel) (let* ((start (- start-degree (/ start-dent 2))) (end (- start (* (- 360 start-dent) length)))) ; (gimp-message (string-append "(intersect-segment nil " (number->string size) " " ; (number->string (deg-to-radian start 'f)) ; " " ; (number->string (deg-to-radian end 'f)) ; ")")) (intersect-segment img size (deg-to-radian start) (deg-to-radian end))) (gimp-edit-bucket-fill layer FG-BUCKET-FILL NORMAL-MODE 100 0 FALSE 0 0) (gimp-selection-none img) )) (define (fround x) (- x (fmod x 1))) (define (fwrap x mod) (- x (* mod (fround (/ x mod))))) (define (anglewrap x) (let ((res (fwrap x (* 2 *pi*)))) (if (< res 0) (+ res (* 2 *pi*)) res))) (define (contains x start end) (let ((low (min start end)) (high (max start end))) (and (<= x max) (>= x min)))) (define (intersect-segment img size start end) (let* ((array (cons-array 24 'double)) (radius (/ size 2)) (cx (/ size 2)) (cy (/ size 2))) (aset array 0 cx) (aset array 1 cy) (let ((xy (prolungate-segment size start))) (aset array 2 (car xy)) (aset array 3 (cadr xy))) (let* ((winkelliste (list (list (* (/ 7 4) *pi*) 1 1) (list (* (/ 5 4) *pi*) 0 1) (list (* (/ 3 4) *pi*) 0 0) (list (* (/ 1 4) *pi*) 1 0))) (i 4)) (let ((wl winkelliste) (finished '()) (e (if (< end start) end 0))) (while (and (not (null? wl)) (not finished)) (let* ((wxy (car wl)) (angle (car wxy)) (x (cadr wxy)) (y (caddr wxy))) (if (and (<= angle start) (>= angle e)) (begin (aset array i (* x size)) (aset array (+ i 1) (* y size)) ; (print (list x y)) (set! i (+ i 2))))) (set! wl (cdr wl)))) (if (and (> end start) (> end 0)) (let ((wl winkelliste) (finished '())) (while (and (not (null? wl)) (not finished)) (let* ((wxy (car wl)) (angle (car wxy)) (x (cadr wxy)) (y (caddr wxy))) (if (>= angle end) (begin (aset array i (* x size)) (aset array (+ i 1) (* y size)) ; (print (list x y)) (set! i (+ i 2))))) (set! wl (cdr wl))))) (let ((xy (prolungate-segment size end))) (aset array i (car xy)) (aset array (+ i 1) (cadr xy))) (set! i (+ i 2)) (aset array i cx) (aset array (+ i 1) cy) (set! i (+ i 2)) ; (list i array)))) (gimp-free-select img i array CHANNEL-OP-INTERSECT TRUE TRUE 1)))) (define (subtract-dent img size mid-angle angle-size) (let* ((array (cons-array (* 3 2) 'double)) (radius (/ size 2)) (cx (/ size 2)) (cy (/ size 2)) (sa (+ mid-angle (/ angle-size 2))) (ea (- mid-angle (/ angle-size 2)))) (aset array 0 cx) (aset array 1 cy) (let ((xy (prolungate-segment size sa))) (aset array 2 (car xy)) (aset array 3 (cadr xy))) (let ((xy (prolungate-segment size ea))) (aset array 4 (car xy)) (aset array 5 (cadr xy))) (gimp-free-select img 6 array CHANNEL-OP-SUBTRACT TRUE TRUE 1))) (define (prolungate-segment size angle) (let ((cx (/ size 2)) (cy (/ size 2)) (sx (cos angle)) (sy (- (sin angle)))) (list (+ cx (* size sx)) (+ cy (* size sy))))) (define (deg-to-radian deg) (anglewrap (fmod (* 2 *pi* (/ deg 360.0)) (* 2 *pi*)))) (define (circle-coords angle size) (let* ((cx (/ size 2)) (cy (/ size 2)) (radius (/ size 2)) (dx (* radius (cos angle))) (dy (* radius (sin angle)))) (list (+ cx dx) (+ cy dy)))) (script-fu-register "script-fu-reaktor-knob" "/Xtns/Script-Fu/My Stuff/Reaktor Knob..." "Create a knob animation for reaktor" "das wesen" "das wesen" "Nov 2005" "" SF-VALUE "Size" "64" SF-VALUE "Width" "10" SF-VALUE "Inactive Width" "5" SF-VALUE "Number of steps" "4" SF-VALUE "Scale steps" "4" SF-VALUE "Start degree" "270" SF-VALUE "Start dent size (degrees)" "30" SF-VALUE "Small dent size (degrees)" "10" SF-COLOR "Active color" '(255 255 255) SF-COLOR "Inactive color" '(40 40 40) SF-COLOR "Background color" '(0 0 0)) ;; (script-fu-reaktor-knob 64 10 5 32 10 270 45 10 '(255 255 255) '(255 0 0) '(0 0 0))