スクリプトでOBSにカウンタを導入する
昨日の夜〜早朝に配信していたVTuber(御伽原江良さん)の耐久ゲーム配信を6時間ほどみてたんですが、
リトライ毎に挑戦回数のテキストを編集するのが大変そうだったのでカウントを補助するOBSのスクリプトを作りました。
スクリプトをダウンロードしてOBSに登録すれば、
ワンクリック(ホットキー登録すればキー1回押し)でカウントできるようになります。
深夜にやってた耐久ゲーム配信のリトライカウント入力(文字入力)で涙でたのでOBSスクリプト作った。 pic.twitter.com/CZdc5OWUH8
— tid (@_tid_) 2019年6月22日
リトライ回数やキル数など、配信で表示する汎用の手動カウンタとして使えます。
設定方法
使い方
シーンにテキストソースを登録
OBSのメニュー
ツール > スクリプト
Text Source
に作ったテキストソースを設定Format
を好きな文字列に変更。(例: 今%d回目) ※%dが現在のカウントに置き換えられます。UP
/DOWN
ボタンをクリックするとカウントアップ(ダウン)Reset
ボタンをクリックするとカウントリセット
テキストのスタイルはテキストソースの設定が使われます。
ホットキー登録
ホットキー登録するとスクリプトウィンドウを開かずにキーボードのキー1回押しでカウントアップ(ダウン)とリセットができます。
個人で使いやすいキーを登録してください。
その他の設定
Start Number
:開始数字。
Step Number
:カウントの刻み。この数値分増減します。
コード
[OBS Script]Sets a text source to act as a tally counter when the source is active. · GitHub
ライセンス
商用・非商用問わず自己責任でご自由にお使いください。
このスクリプトを使用したことで損害が発生しても責任は一切負いません。
おわり
御伽原さんの耐久ゲーム配信のアーカイブはこちら www.youtube.com
WWDC19 とりあえず見たいセッションリスト
概要
Keynote
Platforms State of the Union
Xcode
What’s New in Xcode 11
Getting Started with Xcode
Adopting Swift Packages in Xcode
Debugging in Xcode 11
Testing in Xcode
Creating Great Localized Experiences with Xcode 11
Great Developer Habits
Swift
What’s New in Swift
Modern Swift API Design
Creating Swift Packages
Swift Playgrounds 3
Combine
Combine in Practice
Introducing Combine
Introducing Combine and Advances in Foundation
SwiftUI
Building Custom Views with SwiftUI
Data Flow Through SwiftUI
Accessibility in SwiftUI
Integrating SwiftUI
Introducing SwiftUI: Building Your First App
SwiftUI Essentials
SwiftUI On All Devices
SwiftUI on watchOS
Mastering Xcode Previews
Design
What’s New in iOS and macOS Design
What’s New in iOS Design
Modernizing Your UI for iOS 13
AppKit
What’s New in AppKit for macOS
その他
What’s New in Clang and LLVM
What’s New in App Store Connect
RxSwiftを利用している方がCombineに注目しているようでしたが、現時点ではまだRxのサブセットのように見えました。 iOS 13だけサポートするとしても今すぐRxSwiftを置き換えることはできないと思います。 ただ、iOS 12のサポートを切れる頃にはもっと成長してそうなので今後に期待です。(・・・2年後かな。)
CombineはSwiftUIでも利用するので、Combine → SwiftUIの順に見ていくのが良さそうです。
追記: Shai Mishali さんがRxSwiftと比較したCombineのチートシートを作られています。 medium.com
これを拝見する限り、思ったより網羅されているようです。
一部、?と思ってしまう名前のものがあるので治してくれるといいですね。
アラートを表示する(NSAlert)
アラートの表示
アラートを作る
let alert = NSAlert()
ダイアログとして表示
alert.runModal()
押されたボタンを確認
runModal()
の戻り値で確認できます。
let response = alert.runModal() switch response { case .alertFirstButtonReturn: break case .alertSecondButtonReturn: break case .alertThirdButtonReturn: break default: break }
シートとして表示する
alert.beginSheetModal(for: window, completionHandler: nil)
押されたボタンを確認する
シート表示の第2引数のクロージャで確認できます。
alert.beginSheetModal(for: window) { response in switch response { case .alertFirstButtonReturn: break case .alertSecondButtonReturn: break case .alertThirdButtonReturn: break default: break } }
アラートのカスタマイズ
アイコン
デフォルトではアプリのアイコンが使用されますが変更可能です。
alert.icon = NSImage(named: “Awesome icon”)
スタイル
スタイルは下記の3種類が用意されています。 今のところinformationalとwarningは見た目上の違いはないそうです。 criticalについてはmacOS Human Interface Guidelinesの”Alerts”の章に従って使用するようにします。
informational
alert.alertStyle = .informational
warning
alert.alertStyle = .warning
critical
alert.alertStyle = .critical
メッセージ
- タイトル変更
alert.messageText = “Main Message”
- 追加テキスト変更
alert.informativeText = “Additional information text”
ボタン
addButton(withTitle:)
でボタンを追加できます。
これを使うとデフォルトのボタンは使われなくなります。
1回addButton(withTitle:)
を呼ぶと1個、2回呼ぶと2個…という風にボタンが増えていきます。
任意の数のボタンを追加できますが、3個までが想定されている個数のようです。
ここでは2個のボタンを追加する例をあげます。
alert.addButton(withTitle: “OK”) alert.addButton(withTitle: “Cancel”)
抑制ボタン
“次からこのメッセージを表示しない。”チェックボックスを表示できます。
alert.showsSuppressionButton = true
抑制ボタンのメッセージを変更
抑制ボタンはNSButtonなのでメッセージを変更できます。
alert.suppressionButton?.title = “No thank you”
アクセサリービュー
独自のビューを表示したい時はアクセサリービューとして設定します。 アクセサリービューはNSViewならなんでも表示できます。 抑制ボタンとボタンの間に表示されます。
let textView = NSTextView(frame: NSRect(x: 0, y: 0, width: 200, height: 150)) textView.string = “TEXT IN ACCESSORYVIEW” alert.accessoryView = textView
参考
NSTextViewで折りたたみ
NSTextViewで折りたたみ(フォールディング)は、折りたたみたい文字のグリフをNullGlyphに置き換えることで実現できます。
下記に手順を紹介します。
折りたたむ文字列に目印をつける
折りたたみたい文字に目印となるカスタム属性を設定します。
ここではカスタム属性のキーとして下記の.folding
を定義しているものとします。
// カスタムAttribute extension NSAttributedString.Key { static let folding = NSAttributedString.Key(rawValue: “NSAttributedString.Key.folding”) }
例えば”ABCD”
という文字列があったとして、”BC”
を折りたたみたい場合は”BC”
の範囲にカスタム属性.folding
を設定します。
textView.string = “ABCD” textView.storage?.addAttributes([.folding: true], range: NSRange(location: 1, length: 2))
カスタム属性を設定しただけでは何も起こりません。 次にカスタム属性を目印にしてグリフをNullGlyphに置き換えるようにします。
グリフをNullGlyphに置き換える
カスタム属性を設定した箇所のグリフを変更します。
グリフはNSLayoutManager
で設定するのでサブクラスを作ってグリフを設定するメソッドをオーバーライドします。
class LayoutManager: NSLayoutManager { override func setGlyphs(_ glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSLayoutManager.GlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: NSFont, forGlyphRange glyphRange: NSRange) { // Glyphプロパティで.nullを指定すると該当箇所のGlyphがNULLGlyphとして扱われる var properties = [NSLayoutManager.GlyphProperty](repeating: .null, count: glyphRange.length) for i in 0..<glyphRange.length { let index = glyphRange.location + i if let attrs = textStorage?.attributes(at: index, effectiveRange: nil), attrs[.folding] == nil { properties[i] = props.advanced(by: i).pointee } } super.setGlyphs(glyphs, properties: &properties, characterIndexes: charIndexes, font: aFont, forGlyphRange: glyphRange) } }
次にここで作ったカスタムLayoutManagerをNSTextViewが利用するように設定します。
カスタムLayoutManagerを使用する
NSTextViewのインスタンスを作る時に設定します。
let textStorage = NSTextStorage() let layoutManager = LayoutManager() let textContainer = NSTextContainer() layoutManager.addTextContainer(textContainer) textStorage.addLayoutManager(layoutManager) NSTextView(frame: frame, textContainer: textContainer)
折りたたみを解除するには?
カスタム属性を消去すれば折りたたみは解除されます。
textView.textStorage?.removeAttribute(.folding, range: NSRange(location: 1, length: 2))
まとめ
基本的にiOS(UITextView)でも同じ考え方で折りたたみを実装できます。(メソッドや引数が異なる程度の差です。) また、この方法の応用でIDEによくあるラインフォールディングも実装できます。 折りたたみの範囲を行単位にするだけです。
NSTextViewで文字列にリンクを設定する
任意の文字列にリンクを設定
NSTextStorageにキーがNSAttributedString.Key.link
で値がURL
の属性を設定すれば任意の文字列にリンクを設定できます。
textView.string = "Link to Blog" let url = URL(string: "https://tid-a24.hatenablog.com/")! textView.textStorage?.addAttributes([.link: url], range: NSRange(textView.string))
URL文字列に自動でリンクを設定
NSTextViewにURL文字列が含まれて、そのURL文字列をリンクとして扱いたいなら
isAutomaticLinkDetectionEnabled
プロパティをtrue
にすれば自動でリンクとして設定されます。
textView.isAutomaticLinkDetectionEnabled = true
リンク属性の設定
リンクテキストの文字色やマウスオーバー時のカーソル形状などを変更するにはlinkTextAttributes
プロパティに値を設定します。
デフォルトでは文字色はNSColor.linkColor
でアンダーラインが付いたものになり、マウスオーバー時のカーソル形状は指差しハンドです。
- マウスオーバー時のカーソル形状指定
textView.linkTextAttributes?[.cursor] = NSCursor.pointingHand
- アンダーラインを消す
linkTextAttributes?[NSAttributedString.Key.underlineStyle] = nil
NSPopoverを閉じる方法
BehaviorでNSPopoverの閉じる方法(挙動)を指定します。
let popover = NSPopover() popover.behavior = .transient
Behaviorは3種類定義されています。
applicationDefined
開発者が動作を定義する。(閉じるボタンをつけるなど。)
自動で閉じることはない。transient
NSPopoverからフォーカスが外れると自動で閉じる。semitransient
transientと同じだが、他Window(他のアプリケーション含む)へのフォーカス移動では閉じない。
また、他Windowへフォーカスを移動した後にNSPopoverを表示しているWindowへフォーカスを移動しても閉じない。
基本的にtransient
を使用して、NSPopoverを表示したまま他Windowを操作する必要があればsemitransient
を使えばいいように思います。
macOS appの環境設定:Escapeキーで閉じるようにする
環境設定のWindowをNSPanelにすることでEscapeキーで閉じるようにできます。
これだけでEscapeキー(または⌘-.)で閉じるようになります。