Re: AppKit and CAPI (LWM)
Ouah, very cool ! Thanks a lot Ralph !
Best regards
Denis
Le 4/02/10 16:42, « [NOM] » <[ADRESSE]> a écrit :
>
> On Feb 4, 2010, at 10:07 AM, Denis Pousseur wrote:
>
>> Don't loose your time for me : I will find how to do that exactly if
>> necessary (but I'm not sure because changing my main output-pane for a
>> Nsview will result in a lot of changes in my codes...)
>
> No problem - it was just a matter of cutting down existing code to a simple
> example. Here it is:
>
> warmest regards,
>
> Ralph
>
> ;; --------- simple-bp-capi.lisp ------------
>
> #|
> Copyright (c) 2010 Raffael Cavallaro
>
> All rights reserved.
>
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
> "Software"), to deal in the Software without restriction, including
> without limitation the rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or sell copies of the Software, and to
> permit persons to whom the Software is furnished to do so, subject to
> the following conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
>
> (N.B. this is the MIT license)
>
> |#
>
> ;; Raffael Cavallaro can be reached at raffaelcavallaro@me.com
> ;;
> ;; Simple example of using capi:cocoa-view-pane and NSBezierPath
> ;; lightly tested under LWM 6.0 64-bit Intel and LW Personal 5.1.1
> ;; 32-bit Intel.
> ;;
> ;; Compile and load this file and call:
> ;; (simple-bp-capi-test)
> ;;
> ;; Note that resizing the window will cause the AppKit to call
> ;; drawRect:, so you'll see a new path with new background and
> ;; foreground colors for every resize. If you resize continuously
> ;; you'll see how quickly the LW objc interface can do redraws -
> ;; the AppKit throttles this to about 60 fps. Having such a view
> ;; do animation of bezier paths is simple; add an mp:timer to
> ;; the interface and have it call setNeedsDisplayInRect:, making
> ;; sure to first check that the view still exists using
> ;; objc:objc-object-from-pointer and objc:null-objc-pointer-p.
> ;; Using this method, you can get ~30 paths, full screen, with
> ;; alpha blending and anti-aliasing, @ between 15 and 30 fps on
> ;; reasonably recent hardware.
>
> (use-package :cocoa :objc)
>
> (eval-when (:compile-toplevel :load-toplevel :execute)
> (defmacro @ (&body body) `(objc:invoke ,@body))
> (defmacro @into (&body body) `(objc:invoke-into ,@body))
> (defmacro @pool (&body body) `(objc:with-autorelease-pool () ,@body))
>
> (objc:define-objc-class
> simple-bp-view ()
> ()
> (:objc-class-name "SimpleBPView")
> (:objc-superclass-name "NSView")))
>
> (let* ((*read-default-float-format*
> #+LISPWORKS-32BIT 'single-float
> #+LISPWORKS-64BIT 'double-float))
> ;; NSColor and NSBezierPath want CGFloats which are
> ;; floats on 32-bit Macs, and doubles on 64-bit Macs.
>
>
>
> (defun random-ns-warm-color ()
> (@ "NSColor" "colorWithCalibratedHue:saturation:brightness:alpha:"
> (random .13) ;; red-yellow-orange hue
> (+ .6 (random .4)) ;; fairly saturated
> (+ .8 (random .2)) ;; very bright
> (+ .8 (random .2)))) ;; at least 80% alpha so it shows in foreground
>
> (defun random-ns-cool-color ()
> (@ "NSColor" "colorWithCalibratedHue:saturation:brightness:alpha:"
> (+ .35 (random .15)) ;; blue-green to blue
> (+ .5 (random .5)) ;; somewhat desaturated
> (+ .8 (random .2)) ;; very bright
> (+ .8 (random .2)))) ;; at least 80% alpha
>
>
> (objc:define-objc-method
> ("drawRect:" :void)
> ((self simple-bp-view)
> (rect-to-draw cocoa:ns-rect))
> (declare (ignorable rect-to-draw))
> (block bail-out
> (if (or (null self) ;; don't try to draw if view is gone
> (objc:null-objc-pointer-p (objc:objc-object-pointer self)))
> (return-from bail-out nil)
> (@pool
> (let* ((rect (make-array 4))
> (ns-self (when self (objc:objc-object-pointer self)))
> (bounds-vector (when ns-self (@into rect ns-self "bounds")))
> (background-path ;; just the view's entire bounds rect
> (@ "NSBezierPath" "bezierPathWithRect:" bounds-vector))
> (width (svref rect 2))
> (height (svref rect 3))
> (foreground-path (@ "NSBezierPath" "bezierPath")))
> (declare (ignorable bounds-vector))
> (labels ((rand-xoffset () ;; well within view bounds
> (+ 20 (random (- width 30))))
> (rand-yoffset () ;; ditto
> (+ 20 (random (- height 30))))
> (random-point ()
> (vector (rand-xoffset) (rand-yoffset))))
>
> (@ (random-ns-cool-color) "setFill") ;; set random cool color
> (@ background-path "fill") ;; fill background with it
> ;; make foreground-path a random NSBezierPath within bounds
> (@ foreground-path "moveToPoint:" (random-point))
> (@ foreground-path "curveToPoint:controlPoint1:controlPoint2:"
> (random-point) (random-point) (random-point))
> (@ (random-ns-warm-color) "setFill") ;; set random warm color
> (@ foreground-path "fill"))))))) ;; fill foreground path with it
>
> (capi:define-interface simple-bp-capi-window ()
> ()
> (:panes
> (simple-bp-view-pane capi:cocoa-view-pane
> :view-class "SimpleBPView"
> :init-function
> #'(lambda (pane view)
> (declare (ignorable pane))
> (setf view (objc:objc-object-pointer
> (make-instance
> 'simple-bp-view)))
> view)
> :accessor bp-view-pane
>
> :internal-min-width 550
> :internal-min-height 350))
> (:default-initargs
> :title "Simple Bezier CAPI Window"
> :window-styles '(:internal-borderless))))
>
> (defun simple-bp-capi-test ()
> (capi::display (make-instance 'simple-bp-capi-window)))
>
>
>
> ;; Raffael Cavallaro
> ;; raffaelcavallaro@me.com
>
>
-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique
Tel : 32 (0)2 219 31 09
Mail : denis.pousseur@gmail.com
-------------------------------------------------------