Основы пользовательских патчей
Кварцевый патч Композитора подобен подпрограмме в традиционном языке программирования — патч является основным блоком обработки, выполняющим и приводящим к результату. Пользовательский патч является тем, который Вы пишете путем разделения на подклассы QCPlugIn
класс. Для предоставления доступа к пользовательскому патчу доступным в Кварцевом Композиторе исправляют библиотеку, необходимо упаковать ее как плагин — NSBundle
объект — и установка в надлежащем каталоге. Если Вы хотели бы, можно упаковать больше чем один пользовательский патч в плагине. Вы не должны создавать пользовательский интерфейс для пользовательского патча. Когда Кварцевый Композитор загружает Ваш плагин, он создает пользовательский интерфейс автоматически для каждого пользовательского патча в плагине так, чтобы пользовательские патчи имели тот же взгляд в рабочей области как патчи, встроенные Кварцевому Композитору.
Эта глава обеспечивает обсуждение пользовательских патчей и дает обзор задач, которые необходимо выполнить для создания пользовательского патча. Вы будете видеть, какие аспекты Вашего кода дают начало пользовательскому интерфейсу для пользовательского патча. К концу главы у Вас должна быть довольно хорошая идея того, как начать писать Ваши собственные патчи. Тогда можно считать Патчи Процессора Записи и Запись Потребительских Патчей, чтобы узнать, как записать определенные виды патчей.
Внимательное рассмотрение в пользовательском интерфейсе патча
Патчи в Кварцевом Композиторе, у всех есть тот же основной стиль, как Вы видите на рисунке 1-1. Имя патча наверху патча в строке заголовка патча. Входные порты находятся на левой стороне патча, и выходные порты находятся на правой стороне. Много патчей провайдера не имеют входных портов, потому что они получают данные от внешнего источника, такого как мышь, клавиатура, планшет или MIDI-контроллер. Потребительские патчи не имеют выходных портов, потому что они представляют данные месту назначения. Патчи процессора имеют один или несколько входных портов и один или несколько выходных портов.
Инспектор обеспечивает доступ к параметрам патча. Область Input Parameters содержит те же параметры, представленные входными портами. Это предоставляет возможность вручную корректировать входные значения вместо того, чтобы предоставить значения через входные порты. Сравните патч Заварного чайника, показанный на рисунке 1-1 с рисунком 1-2. Вы будете видеть, что порты совпадают с входными параметрами.
Некоторые патчи также имеют область Settings, как показано на рисунке 1-3, предоставляющем поддержку для конфигурирования настроек, значения которых любой не может быть представлен одним из типов данных стандартного порта (см. Таблицу 1-1), или то управление расширенные настройки.
От пользовательского кода патча для исправления пользовательского интерфейса
Пользовательский патч является подклассом QCPlugIn
класс. Кварцевый Композитор создает порты ввода и вывода на пользовательском патче от динамических свойств Objective-C подкласса. Свойства, имя которых начинается input
(и один из поддерживаемых типов), появится как входной порт на патче. Свойства, имя которых начинается output
(и один из поддерживаемых типов), появится как output
порт на патче. Перечисление 1-1 показывает код, создающий подкласс QCPlugIn
и объявляет ввод того и один выходной параметр. Поскольку Вы читаете этот раздел, который Вы будете видеть, как тот код касается получающегося пользовательского патча в Кварцевом Композиторе.
Перечисление 1-1 подкласс и свойства для обрабатывающего пользовательскую строку патча
@interface iPatchPlugIn : QCPlugIn |
{ |
} |
@property(assign) NSString* inputString; |
@property(assign) NSString* outputString; |
@end |
Можно реализовать attributesForPropertyPortWithKey:
метод для отображения имени каждого свойства (такой как inputString
или outputString
) к паре ключ/значение для соответствующего параметра патча. Перечисление 1-2 показывает реализацию этого метода для свойств, объявленных в Перечислении 1-1. Для каждого свойства метод возвращает словарь, содержащий имя порта и его значение по умолчанию, если таковые имеются. Этот пример возвращает имя порта Name
для свойства это называют inputString
. Это возвращается iName
для свойства это называют outputString
.
Перечисление 1-2 подпрограмма, возвращающая атрибуты для портов свойства
+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key |
{ |
if([key isEqualToString:@"inputString"]) |
return [NSDictionary dictionaryWithObjectsAndKeys: |
@"Name", QCPortAttributeNameKey, |
@"Pod", QCPortAttributeDefaultValueKey, |
nil]; |
if([key isEqualToString:@"outputString"]) |
return [NSDictionary dictionaryWithObjectsAndKeys: |
@"iName", QCPortAttributeNameKey, |
nil]; |
return nil; |
} |
Рисунок 1-4 показывает патч, что Кварцевый Композитор создает в результате объявлений свойства и attributesForPropertyPortWithKey:
метод. Обратите внимание на то, что входные значения только для чтения — Ваш пользовательский код патча читает входные значения и обрабатывает их в некотором роде. Ваш пользовательский код патча может записать в выходные порты, а также считать их текущую стоимость.
Если Вы не используете свойства, или если Ваш пользовательский патч должен изменить число портов во время выполнения, можно использовать QCPlugIn
методы, чтобы динамично добавить и удалить порты ввода и вывода и связанные методы, чтобы установить и получить значения. Эти методы описаны в Ссылке класса QCPlugIn:
Можно определить строку, указывающую практическое имя для пользовательского патча. Это - имя, появляющееся как заголовок патча. Необходимо также определить строку описания, кратко говорящую то, что делает пользовательский патч. Например:
#define kQCPlugIn_Name @"iPatch" |
#define kQCPlugIn_Description @"Converts any name to an \"iName\"" |
Тогда необходимо реализовать attributes
метод так, чтобы Ваш пользовательский патч возвратил словарь, содержащий имя и описание. Перечисление 1-3 показывает attributes
метод для iPatch пользовательского патча.
Перечисление 1-3 подпрограмма, возвращающая пользовательское имя патча и описание
+ (NSDictionary*) attributes |
{ |
return [NSDictionary dictionaryWithObjectsAndKeys: |
@"Name", QCPlugInAttributeNameKey, |
@"Convert any name to an \"iName\"", QCPlugInAttributeDescriptionKey, |
nil]; |
} |
Описание появляется в Кварцевом Композиторе, когда патч выбран в Создателе Патча и когда пользователь нависает указатель над строкой заголовка патча в рабочей области.
Необходимо установить режим выполнения для пользовательского патча путем реализации executionMode
метод. Метод возвращает надлежащий постоянный режим выполнения, который представляет Кварцевый тип патча Композитора — провайдер, процессор или потребитель.
kQCPlugInExecutionModeProvider
когда выходные значения необходимы, но самое большее один раз на кадр, указывает для выполнения. Этот режим для пользовательских патчей, вытягивающих данные из внешнего источника, такого как видео, мышь, MIDI-устройство, канал RSS, и т.д.kQCPlugInExecutionModeProcessor
указывает для выполнения, когда выходные значения необходимы и когда изменяются входные значения.kQCPlugInExecutionModeConsumer
указывает для выполнения каждого кадра. Этот тип пользовательского патча вытягивает данные от других и представляет его месту назначения.
Пользовательский патч должен установить зависимость времени путем реализации timeMode
метод. Метод возвращает один из следующего раза константы режима:
kQCPlugInTimeModeNone
не зависит вовремя.kQCPlugInTimeModeIdle
не зависит вовремя, но должен дать системе некоторое время для обработки.kQCPlugInTimeModeTimeBase
определили основу времени системой, и пользовательский патч использует время в своих вычислениях для результата.
Если пользовательский патч будет использовать режим основы времени, то патч будет иметь опцию, позволяющую пользователю устанавливать основу времени для порождения, локальный, или внешний, как показано на рисунке 1-5.
Свойство и типы данных порта
Свойства Objective-C 2.0 должны быть одним из типов данных, перечисленных в Таблице 1-1. Кварцевый Композитор отображает тип данных свойства на надлежащий тип порта. Константы типа для портов, которые Ваш пользовательский патч создает во время выполнения, перечислены в столбце Custom Port Type таблицы, рядом с классом Objective C, связанным со значением порта. Если Ваш пользовательский патч требует данных, которые не могут быть получены одним из типов данных ниже, видеть Внутренние Настройки.
Порт | Тип свойства Objective-C 2.0 | Пользовательский тип порта | Класс Objective C |
---|---|---|---|
Булевская переменная |
|
|
|
Индекс |
|
|
|
Число |
|
|
|
Строка |
|
|
|
Цвет |
|
|
|
Структура |
|
|
|
Изображение (вводится) |
|
|
|
Изображение (выводится) |
|
|
|
Изображения в Кварцевом Композиторе являются непрозрачными объектами, соответствующими протоколам. Используя протоколы избегает ограничений определенного типа изображения, а также несоответствий типов. Это также получает лучшую производительность, потому что Кварцевый Композитор задерживает пиксельное вычисление, пока это не необходимо.
Поддерживаемые форматы пикселя для изображений:
ARGB8
— Альфа на 8 битов, красное, зеленое, синее, целое без знака на 8 битов на 8 битов на 8 битовBGRA8
— Синяя, зеленая, красная, альфа на 8 битов на 8 битов на 8 битов на 8 битов, целое без знакаRGBAf
— Красная, зеленая, синяя, альфа на 32 бита на 32 бита на 32 бита на 32 бита, с плавающей точкойl8
— Яркость на 8 битов, целое без знакаlf
— Яркость на 32 бита, с плавающей точкой
Входные изображения являются непрозрачными исходными объектами, соответствующими QCPlugInInputImageSource
протокол. Для использования изображения в качестве входного параметра к пользовательскому патчу объявите его как свойство:
@property(assign) id<QCPlugInInputImageSource> inputImage; |
Выходные изображения являются непрозрачными объектами провайдера, соответствующими QCPlugInOutputImageProvider
протокол. Для использования изображения в качестве выходного параметра для пользовательского патча объявите его как свойство:
@property(assign) id<QCPlugInOutputImageProvider> outputImage; |
Запись Патчей Обработки изображений показывает, как определить методы QCPlugInInputImageSource
и QCPlugInOutputImageProvider
протоколы. См. также Ссылку на протокол QCPlugInInputImageSource и Ссылку на протокол QCPlugInOutputImageProvider.
Внутренние настройки
Пользовательские параметры патча, не подходящие как входные порты, могут быть добавлены к области Settings инспектора для патча. Несколько причин, почему Вы могли бы хотеть использовать внутренние настройки:
Параметр не может быть представлен одним из типов данных, перечисленных в Таблице 1-1. Посмотрите, например, кривую интерполяции, показанную на рисунке 1-6.
Значение по умолчанию работ параметра в большинстве случаев и должно быть изменено только хорошо осведомленным пользователем.
Это не целесообразно анимировать параметр.
Для таких случаев Ваш пользовательский патч должен обеспечить пользовательский интерфейс для редактирования этих значений. Кварцевый Композитор вставляет Ваш настроенный пользовательский интерфейс в область Settings инспектора для патча. Внутренние настройки доступны посредством кодирования значения ключа. Самый простой способ реализовать их как свойства Objective-C 2.0. Перечисление 1-4 показывает два типичных объявления для переменных экземпляра свойства.
Код перечисления 1-4, объявляющий переменные экземпляра свойства
@property(copy) NSColor* systemColor; |
@property(copy) MyConfiguration* systemConfiguration; |
Ваш QCPlugIn
подкласс должен реализовать plugInKeys
метод так, чтобы это возвратило список ключей для внутренних настроек. plugInKeys
метод для systemColor
и systemConfiguration
свойства показаны в Перечислении 1-5. Удостоверьтесь, что завершили список с nil
. (См., что значение ключа кодирует руководство по программированию.)
Перечисление 1-5 реализация plugInKeys
метод
+ (NSArray*) plugInKeys |
{ |
return [NSArray arrayWithObjects: @“systemColor”, |
@“systemConfiguration”, |
nil] |
} |
Вы используете Интерфейсного Разработчика для создания пользовательского интерфейса для редактирования внутренних настроек. Интерфейс является объектом представления (NSView
или NSView
подкласс), которым управляют через экземпляр QCPlugInViewController
. Этот экземпляр действует как контроллер между пользовательским экземпляром патча и представлением, содержащим средства управления. Для пера для загрузки должным образом сменный класс должен реализовать createViewController
метод QCPlugIn
и возвратите экземпляр QCPlugInViewController
инициализированный с корректным именем пера. В этом примере, показанном в Перечислении 1-6, имя MyPlugIn
.
Код перечисления 1-6, реализующий контроллер представления
- (QCPlugInViewController*) createViewController |
{ |
return [[QCPlugInViewController alloc] initWithPlugIn:self |
viewNibName:@”MyPlugIn”]; |
} |
Используя привязку Какао для средств управления в Вашем пользовательском интерфейсе не требует никакого кода. Просто используйте plugIn.XXX
как ключевой путь модели, где XXX
соответствующий ключ для внутренней установки. Если Вы предпочитаете, можно разделить на подклассы QCPlugInViewController
реализовать обычную коммуникационную модель целевого действия. (Также необходимо удостовериться, что Вы не автовыпускаете контроллер. Тогда необходимо соединить средства управления в пере к контроллеру владельца.)
Когда Вы читаете или пишете файл состава, использующий пользовательский патч, внутренние настройки сериализируются. Сериализация является автоматической для любой установки, класс которой соответствует NSCoding
протокол, такой как NSColor
. Например, systemColor
свойство, определенное в Перечислении 1-4, не требует никакого действия с Вашей стороны; система сериализирует его автоматически.
Для настроек, не соответствующих NSCoding
протокол, необходимо переопределить следующие методы:
serializedValueForKey:
преобразовывает значение в его сериализированное представление.setSerializedValue:forKey:
преобразовывает из сериализированного представления назад исходному значению.
Например, systemConfiguration
свойство, определенное в Перечислении 1-4, сериализируется как показано в Перечислении 1-7. Сериализированное значение должно быть классом списка свойств такой как NSString
, NSNumber
, NSDate
, NSArray
, или NSDictionary
или nil
.
Код перечисления 1-7, переопределяющий методы сериализации для данных конфигурации системы
- (id) serializedValueForKey:(NSString*)key |
{ |
if([key isEqualToString:@"systemConfiguration"]) |
return [self.systemConfiguration data]; |
// Ensure this has a data method |
return [super serializedValueForKey:key]; |
} |
- (void) setSerializedValue:(id)serializedValue |
forKey:(NSString*)key |
{ |
// System config is subclass of NSObject. |
// It's up to you to keep track of the version. |
if([key isEqualToString:@"systemConfiguration"]) |
self.systemConfiguration |
= [MyConfiguration configurationWithData:serializedValue]; |
else |
[super setSerializedValue:serializedValue forKey:key]; |
} |
Пользовательское выполнение патча
Кварцевый Композитор предполагает, что следующие утверждения являются истиной для Вашего QCPlugIn
подкласс:
Могут быть многократные экземпляры пользовательского патча. Кварцевый Композитор создает один экземпляр
QCPlugIn
разделите на подклассы каждый раз, когда пользовательский патч появляется в составе.Пользовательский патч работает правильно, даже когда он не выполняется на основном потоке.
Пользовательский патч не требует, чтобы цикл выполнения присутствовал, и работает. (При необходимости в цикле выполнения тогда необходимо установить цикл выполнения на вторичном потоке и связаться с ним.)
execute:atTime:withArguments:
метод QCPlugIn
в основе пользовательского патча. Метод обычно:
Читает значения из входных портов или получает данные от источника
Выполняет вычисления, принимая во внимание время, при необходимости
Или пишет результат в выходные порты или представляет содержание месту назначения
Ваш execute:atTime:withArguments:
метод должен получить доступ к своим портам свойства только при необходимости. Когда Вы можете, значения кэша в циклах, а не неоднократно читать их из порта.
Когда Кварцевый механизм Композитора представляет, он вызывает методы, связанные с выполнением пользовательского патча. Кварцевый Композитор передает непрозрачный объект — т.е. контекст выполнения, соответствующий QCPlugInContext
протокол — к этим методам. Вы не должны ни сохранять контекст, ни использовать его за пределами методов выполнения. Удостоверьтесь, что Вы не пишете значения во входные порты (входные порты только для чтения).
QCPlugInContext
протокол содержит много полезных методов для того, чтобы получить информацию о месте назначения рендеринга, включая:
bounds
возвращает границы, выраженные в Кварцевых модулях Композитора (–1.0
к1.0
).colorSpace
возвращает пространство цвета вывода.CGLContextObj
возвращает контекст CGL для выполнения рендеринга к.
Протокол также обеспечивает утилиты для журналирования сообщений и получения словаря информации о пользователе. Словарь информации о пользователе совместно используется со всеми экземплярами пользовательского патча в той же сменной среде контекста. Словарь был разработан тот путь к разрешению делящейся информации между пользовательскими экземплярами патча. Для получения дополнительной информации об этих методах посмотрите Ссылку на протокол QCPlugInContext.
Шаблон QCPlugIn в XCode
XCode обеспечивает два шаблона, который делает его прямым, чтобы записать и упаковать пользовательские патчи. Один шаблон для пользовательских патчей, не требующих области Settings. Другой шаблон включает файл пера для области Setting. Для каждого шаблона XCode обеспечивает скелетные файлы и методы, которые необходимы, и называет файлы соответственно. Рисунок 1-7 показывает файлы, автоматически создаваемые XCode для Кварцевого названного проекта плагина Композитора iPatch
.
XCode автоматически называет файлы с помощью названия проекта, которое Вы предоставляете. Это файлы по умолчанию, предоставленные XCode.
<ProjectName>PlugIn.m
файл реализации для пользовательского патча. Необходимо изменить этот файл.<ProjectName>PlugIn.h
интерфейсный файл для пользовательского патча. Необходимо изменить этот файл.Info.plist
содержит свойства плагина, такие как область разработки, идентификатор пакета, название продукта и aQCPlugInClasses
ключ, перечисляющий классы для каждого пользовательского патча в плагине. Необходимо изменить Info.plist и удостовериться, что значение связалось сQCPlugInClasses
ключ корректен. Значение по умолчанию для этого ключа основывается на названии проекта, которое Вы предоставляете, таким образом, Вы не должны должны быть изменять его, если Вы не планируете включать больше чем один пользовательский патч в пакет.
Интерфейсный файл объявляет подкласс QCPlugIn
. XCode автоматически называет подкласс <ProjectName>PlugIn
. Например, если Вы предоставляете Number2Color
как название проекта, интерфейсное использование файла Number2ColorPlugIn
как имя подкласса.
Файл реализации содержит эти методы QCPlugIn
класс, который необходимо изменить в целях:
Существуют другие методы QCPlugIn
если в шаблоне, который можно реализовать в подходящих случаях. (См. также Ссылку класса QCPlugIn.)
Файл реализации, предоставленный XCode, содержит два важных оператора, которые Вы не должны изменять и тот, который необходимо изменить. Этот оператор не должен быть изменен или удален:
#import <OpenGL/CGLMacro.h>
Используя CGLMacro.h
улучшает производительность. Включение этого оператора позволяет Кварцевому Композитору оптимизировать свое использование OpenGL путем обеспечения локальной переменной контекста и кэширования текущего средства рендеринга в той переменной. Даже если пользовательский патч не содержит сам код OpenGL, необходимо сохранить этот оператор. Если Ваш пользовательский патч содержит код OpenGL, необходимо объявить локальную переменную и установить текущий контекст в него. Например:
#import <OpenGL/CGLMacro.h>
CGLContext cgl_ctx = myContext;
где myContext
текущий контекст.
Посмотрите Используя OpenGL в Пользовательском Патче и Руководстве по программированию OpenGL для Mac для получения дополнительной информации.
Оператор, определяющий пользовательское имя патча, автоматически заполнен - в XCode на основе названия проекта, которое Вы предоставляете. Если имя патча уникально в контексте Кварцевого Создателя Патча Композитора, чтобы помочь пользователю отличить патчи, лучше. Если имя не будет уникально, то Ваш патч будет трудно использовать. Так, измените этот оператор.
#define kQCPlugIn_Name @"<ProjectName>"
XCode обеспечивает определение по умолчанию для пользовательского описания патча:
#define kQCPlugIn_Description @"Converts any name to an \"iName\""
Необходимо изменить эту строку так, чтобы она описала пользовательский патч. Если имя патча не уникально, лучше описывать, как Ваш патч отличается от другого патча того же имени. Вы также захотите обеспечить локализованные строки. (Для получения дополнительной информации о локализации посмотрите Строковые Файлы.)
Упаковка, устанавливая и тестируя пользовательские патчи
Необходимо упаковать Кварцевого Композитора пользовательский патч как стандартный пакет Какао. Можно упаковать больше чем один пользовательский патч в пакете. QCPlugIn
шаблон делает его тривиальным для упаковки пользовательских патчей; посмотрите Шаблон QCPlugIn в XCode.
Пакет Info.plist
файл должен иметь запись для каждого QCPlugIn
подкласс это находится в пакете. Перечисление 1-8 показывает запись списка свойств для пакета, содержащего два пользовательских патча: MyColorGenerator
и MyNumberCruncher
.
Записи перечисления 1-8 в Info.plist
файл
<key>QCPlugInClasses</key> |
<array> |
<string>MyColorGenerator</string> |
<string>MyNumberCruncher</string> |
</array> |
При создании пакетов необходимо предназначаться 32-разрядный, 64-разрядный, PowerPC и архитектуры Intel.
Можно сделать пользовательский патч доступным для любого приложения, использующего Кварцевого Композитора путем установки плагина, содержащего пользовательский патч в /Library/Graphics/Quartz Composer Plug-Ins
или ~/Library/Graphics/Quartz Composer Plug-Ins
. Когда Кварцевый Композитор запускается, это автоматически загружает плагин так, чтобы все пользовательские патчи, содержавшиеся в плагине, обнаружились в Создателе Патча.
Можно принять решение вместо этого включать пользовательский код патча в комплект приложений. Вы могли бы хотеть сделать это или чтобы управлять использованием пользовательских патчей или потому что они полезны только для приложения, в которое Вы встраиваете их. Для предоставления доступа к пользовательскому патчу доступным для приложения зарегистрируйте подкласс QCPlugIn
класс с помощью registerPlugInClass:
метод. Если Вы хотите ограничить доступ к плагину, содержащему один или несколько пользовательских патчей, можно загрузить плагин из любого расположения путем вызова метода loadPlugInAtPath:
.
Необходимо удостовериться, что пользовательский патч работает должным образом при помощи его в Кварцевом приложении Композитора. При использовании цели Сборки и Копии XCode автоматически копирует созданный плагин в ~/Library/Graphics/Quartz Composer Plug-Ins
и затем Кварцевый Композитор запусков.
Если Вы сделаете какой-либо из следующих, то пользовательские патчи в Вашем плагине не появятся как патчи в Создателе Патча:
Не удается включать имя класса для
QCPlugInClasses
ключ или пишет имя c орфографическими ошибками. Имя класса вInfo.plist
файл должен соответствовать имяQCPlugIn
подкласс.Неправильно объявите свойства. Свойства, представляющие порты, должны использовать один из поддерживаемых типов. (См. Таблицу 1-1.)
Выберите сменное имя, конфликтующее с другим Кварцевым пакетом плагина Композитора. Сменное имя должно быть уникальным. Однако пользовательские имена патча не требуются, чтобы быть уникальными. Но для удобства пользования, это - хорошая идея выбрать уникальные, дескриптивные пользовательские имена патча.
Можно проверить, что система входит в систему Консоль для сообщений об ошибках от Кварцевого Композитора.