Archive for the 'Myriad Helpers' Category

2013/02/11 AppleScriptObjCでMyriad Helpersの三角関数を使ってWindowを円運動

AppleScriptObjCで、三角関数を使ってWindowを円運動させるサンプルです。

三角関数を使ってWindowを円軌道(純粋な円運動だと見栄えがしないので楕円にしていますが)で動かすという、きわめて基礎的な処理です。

curculwin.png

Objective-Cのプログラム内ではsin/cos/tanを使えるものの、AppleScriptObjCプログラム内ではこれらの関数は使えません。

Shane StanleyによるAppleScriptObjCのバイブル「AppleScriptObjC Explored」に、AppleScriptObjCから使うと便利な……逆をいえばAppleScriptObjCの弱点を補うためのObjective-Cのコード「Myriad Helpers」が含まれています。dateの変換や取得、alias→URL変換、そしてこの三角関数(sin/cos/tan/asin/acos/atan/sinh/cosh/tanh/asinh/acosh/atanh/log/log10)の呼び出しなどがそれです。

この「Myriad Helpers」のv2.0がmacosxautomation.comのサイト上からダウンロードできるようになっています

Sal SoghoianとShane Stanleyの合作によるとおぼしきこのAppleScript情報サイト「macosxautomation.com」、本来「AppleScriptObjC Explored」を買わないと入手できない「Myriad Helpers」をなぜフリーでダウンロードできるようにしてあるのか、どういう取引が2者の間で行われたかをいろいろ考えてしまうものですが……フリーで配布しているので、これを使ったサンプルプロジェクトを公開しても問題はないということに。

興味深いのは、この「Myriad Helpers v2.0」がgarbage-collectedなプロジェクトでもAutomatic Reference Countingが有効になっているプロジェクトに組み込んでもビルドできること(正確にいえば、それをわざわざ明記してあること)。

次のOS X 10.9で提供されるAppleScriptObjCの処理系はAutomatic Reference Countingが有効になっているプロジェクトが前提になるだろう、ということが伺われます。ただ、Mac OS X 10.6までさかのぼってその変更が反映されるかどうか……といったところでしょうか。実際問題、AppleScriptObJCのプロジェクトにさまざまなObjective-Cのプログラムを突っ込んで利用するような場合に、garbage-collectedな設定でビルドできないフレームワークなどもあったりして、解決してほしい問題の筆頭であることも事実です。

最初のサンプルは、clicked_ハンドラで連続してウィンドウを円運動させるもの。ウィンドウ上のテキストフィールド上に入れた数値を半径とした円運動を行わせます。ただし、1回だけ。

 Xcodeプロジェクトのダウンロード

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– circulateWin

– Created by Takaaki Naganoya on 2013/02/11.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  property parent : class “NSObject”
  
property aWin : missing value
  
  property ObjWithF : missing value
  
property aStrF : missing value
  
  on applicationWillFinishLaunching_(aNotification)
    – Insert code here to initialize your application before any files are opened
  end applicationWillFinishLaunching_
  
  on applicationShouldTerminate_(sender)
    – Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
  on clicked_(sender)
    
    –set {origin:{x:n, y:m}, |size|:{|width|:n2, height:m2}} to (aWin’s frame()) as record
    
    set aNum to aStrF’s doubleValue()
    
set aNum to aNum as number
    
    
    repeat with i from 1 to 360 by 1
      
      set aSin to ObjWithF’s fordTrig_({“sin”, i, true})
      
set aCos to ObjWithF’s fordTrig_({“cos”, i, true})
      
      set x to ((aNum * aSin) + aNum) * 2
      
set y to (aNum * aCos) + aNum
      
      aWin’s setFrame_display_animate_({{x, y}, {200, 200}}, true, true)
      
      
    end repeat
    
  end clicked_
  
  
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

もうひとつは、0.1秒ごとのタイマー割り込みで円運動させるもの。割り込みで処理するので、それなりのCPUパワーとそれなりのGPUを積んでいれば、マシンに対する負荷もそれほど大きくないでしょう。

 Xcodeプロジェクトのダウンロード

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– circulateWin

– Created by Takaaki Naganoya on 2013/02/11.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  property parent : class “NSObject”
  
property aWin : missing value
  
  property ObjWithF : missing value
  
property aStrF : missing value
  
  property NSTimer : class “NSTimer”
  
property aDegree : 1
  
  
  property aNum : 0
  
  on applicationWillFinishLaunching_(aNotification)
    
    set aDegree to 1
    
    
  end applicationWillFinishLaunching_
  
  on applicationShouldTerminate_(sender)
    – Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
  on clicked_(sender)
    
    –set {origin:{x:n, y:m}, |size|:{|width|:n2, height:m2}} to (aWin’s frame()) as record
    
    set aNum to aStrF’s doubleValue()
    
set aNum to aNum as number
    
    NSTimer’s scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(0.1, me, “timer1Fired:”, “Whatever”, true)
    
    
  end clicked_
  
  
  
  on timer1Fired_(sender)
    
    set aDegree to incrementDegree_(aDegree)
    
    set aSin to ObjWithF’s fordTrig_({“sin”, aDegree, true})
    
set aCos to ObjWithF’s fordTrig_({“cos”, aDegree, true})
    
    set x to ((aNum * aSin) + aNum) * 2
    
set y to (aNum * aCos) + aNum + 100
    
    aWin’s setFrame_display_animate_({{x, y}, {200, 200}}, true, true)
    
    
  end timer1Fired_
  
  
  on incrementDegree_(aDeg)
    if aDeg > 360 then
      set aDeg to 1
    else
      return (aDeg + 1)
    end if
  end incrementDegree_
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に