Основы пользовательских патчей

Кварцевый патч Композитора подобен подпрограмме в традиционном языке программирования — патч является основным блоком обработки, выполняющим и приводящим к результату. Пользовательский патч является тем, который Вы пишете путем разделения на подклассы QCPlugIn класс. Для предоставления доступа к пользовательскому патчу доступным в Кварцевом Композиторе исправляют библиотеку, необходимо упаковать ее как плагинNSBundle объект — и установка в надлежащем каталоге. Если Вы хотели бы, можно упаковать больше чем один пользовательский патч в плагине. Вы не должны создавать пользовательский интерфейс для пользовательского патча. Когда Кварцевый Композитор загружает Ваш плагин, он создает пользовательский интерфейс автоматически для каждого пользовательского патча в плагине так, чтобы пользовательские патчи имели тот же взгляд в рабочей области как патчи, встроенные Кварцевому Композитору.

Эта глава обеспечивает обсуждение пользовательских патчей и дает обзор задач, которые необходимо выполнить для создания пользовательского патча. Вы будете видеть, какие аспекты Вашего кода дают начало пользовательскому интерфейсу для пользовательского патча. К концу главы у Вас должна быть довольно хорошая идея того, как начать писать Ваши собственные патчи. Тогда можно считать Патчи Процессора Записи и Запись Потребительских Патчей, чтобы узнать, как записать определенные виды патчей.

Внимательное рассмотрение в пользовательском интерфейсе патча

Патчи в Кварцевом Композиторе, у всех есть тот же основной стиль, как Вы видите на рисунке 1-1. Имя патча наверху патча в строке заголовка патча. Входные порты находятся на левой стороне патча, и выходные порты находятся на правой стороне. Много патчей провайдера не имеют входных портов, потому что они получают данные от внешнего источника, такого как мышь, клавиатура, планшет или MIDI-контроллер. Потребительские патчи не имеют выходных портов, потому что они представляют данные месту назначения. Патчи процессора имеют один или несколько входных портов и один или несколько выходных портов.

  Множество рисунка 1-1 Кварцевых патчей Композитора
A variety of Quartz Composer patches

Инспектор обеспечивает доступ к параметрам патча. Область Input Parameters содержит те же параметры, представленные входными портами. Это предоставляет возможность вручную корректировать входные значения вместо того, чтобы предоставить значения через входные порты. Сравните патч Заварного чайника, показанный на рисунке 1-1 с рисунком 1-2. Вы будете видеть, что порты совпадают с входными параметрами.

  Область The Input Parameters рисунка 1-2 для патча Заварного чайника
The Input Parameters pane for the Teapot patch

Некоторые патчи также имеют область Settings, как показано на рисунке 1-3, предоставляющем поддержку для конфигурирования настроек, значения которых любой не может быть представлен одним из типов данных стандартного порта (см. Таблицу 1-1), или то управление расширенные настройки.

  Область The Settings рисунка 1-3 для патча Средства форматирования Даты
The Settings pane for the Date Formatter patch

От пользовательского кода патча для исправления пользовательского интерфейса

Пользовательский патч является подклассом 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: метод. Обратите внимание на то, что входные значения только для чтения — Ваш пользовательский код патча читает входные значения и обрабатывает их в некотором роде. Ваш пользовательский код патча может записать в выходные порты, а также считать их текущую стоимость.

Рисунок 1-4  получающийся патч
The resulting patch

Если Вы не используете свойства, или если Ваш пользовательский патч должен изменить число портов во время выполнения, можно использовать 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 метод. Метод возвращает надлежащий постоянный режим выполнения, который представляет Кварцевый тип патча Композитора — провайдер, процессор или потребитель.

Пользовательский патч должен установить зависимость времени путем реализации timeMode метод. Метод возвращает один из следующего раза константы режима:

Если пользовательский патч будет использовать режим основы времени, то патч будет иметь опцию, позволяющую пользователю устанавливать основу времени для порождения, локальный, или внешний, как показано на рисунке 1-5.

Рисунок 1-5  основа времени, устанавливающая для патча Интерполяции
The time base setting for the Interpolation patch

Свойство и типы данных порта

Свойства Objective-C 2.0 должны быть одним из типов данных, перечисленных в Таблице 1-1. Кварцевый Композитор отображает тип данных свойства на надлежащий тип порта. Константы типа для портов, которые Ваш пользовательский патч создает во время выполнения, перечислены в столбце Custom Port Type таблицы, рядом с классом Objective C, связанным со значением порта. Если Ваш пользовательский патч требует данных, которые не могут быть получены одним из типов данных ниже, видеть Внутренние Настройки.

Табличные 1-1  отображения Типа данных

Порт

Тип свойства Objective-C 2.0

Пользовательский тип порта

Класс Objective C

Булевская переменная

BOOL

QCPortTypeBoolean

NSNumber

Индекс

NSUInteger

QCPortTypeIndex

NSNumber

Число

double

QCPortTypeNumber

NSNumber

Строка

NSString *

QCPortTypeString

NSString

Цвет

CGColorRef

QCPortTypeColor

CGColorRef

Структура

NSDictionary *

QCPortTypeStructure

NSDictionary

Изображение (вводится)

id<QCPlugInInputImageSource>

QCPortTypeImage

(id)<QCPlugInInputImageSource>

Изображение (выводится)

id <QCPlugInOutputImageProvider>

QCPortTypeImage

(id)<QCPlugInOutputImageProvider>

Изображения в Кварцевом Композиторе являются непрозрачными объектами, соответствующими протоколам. Используя протоколы избегает ограничений определенного типа изображения, а также несоответствий типов. Это также получает лучшую производительность, потому что Кварцевый Композитор задерживает пиксельное вычисление, пока это не необходимо.

Поддерживаемые форматы пикселя для изображений:

Входные изображения являются непрозрачными исходными объектами, соответствующими QCPlugInInputImageSource протокол. Для использования изображения в качестве входного параметра к пользовательскому патчу объявите его как свойство:

@property(assign) id<QCPlugInInputImageSource> inputImage;

Выходные изображения являются непрозрачными объектами провайдера, соответствующими QCPlugInOutputImageProvider протокол. Для использования изображения в качестве выходного параметра для пользовательского патча объявите его как свойство:

@property(assign) id<QCPlugInOutputImageProvider> outputImage;

Запись Патчей Обработки изображений показывает, как определить методы QCPlugInInputImageSource и QCPlugInOutputImageProvider протоколы. См. также Ссылку на протокол QCPlugInInputImageSource и Ссылку на протокол QCPlugInOutputImageProvider.

Внутренние настройки

Пользовательские параметры патча, не подходящие как входные порты, могут быть добавлены к области Settings инспектора для патча. Несколько причин, почему Вы могли бы хотеть использовать внутренние настройки:

Рисунок 1-6  Две демонстрационных области Настроек
Two sample Settings panesTwo sample Settings panes

Для таких случаев Ваш пользовательский патч должен обеспечить пользовательский интерфейс для редактирования этих значений. Кварцевый Композитор вставляет Ваш настроенный пользовательский интерфейс в область 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 протокол, необходимо переопределить следующие методы:

Например, 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 подкласс:

execute:atTime:withArguments: метод QCPlugIn в основе пользовательского патча. Метод обычно:

Ваш execute:atTime:withArguments: метод должен получить доступ к своим портам свойства только при необходимости. Когда Вы можете, значения кэша в циклах, а не неоднократно читать их из порта.

Когда Кварцевый механизм Композитора представляет, он вызывает методы, связанные с выполнением пользовательского патча. Кварцевый Композитор передает непрозрачный объект — т.е. контекст выполнения, соответствующий QCPlugInContext протокол — к этим методам. Вы не должны ни сохранять контекст, ни использовать его за пределами методов выполнения. Удостоверьтесь, что Вы не пишете значения во входные порты (входные порты только для чтения).

QCPlugInContext протокол содержит много полезных методов для того, чтобы получить информацию о месте назначения рендеринга, включая:

Протокол также обеспечивает утилиты для журналирования сообщений и получения словаря информации о пользователе. Словарь информации о пользователе совместно используется со всеми экземплярами пользовательского патча в той же сменной среде контекста. Словарь был разработан тот путь к разрешению делящейся информации между пользовательскими экземплярами патча. Для получения дополнительной информации об этих методах посмотрите Ссылку на протокол QCPlugInContext.

Шаблон QCPlugIn в XCode

XCode обеспечивает два шаблона, который делает его прямым, чтобы записать и упаковать пользовательские патчи. Один шаблон для пользовательских патчей, не требующих области Settings. Другой шаблон включает файл пера для области Setting. Для каждого шаблона XCode обеспечивает скелетные файлы и методы, которые необходимы, и называет файлы соответственно. Рисунок 1-7 показывает файлы, автоматически создаваемые XCode для Кварцевого названного проекта плагина Композитора iPatch.

Рисунок 1-7  файлы в Кварцевом проекте плагина Композитора
The files in a Quartz Composer plug-in projectThe files in a Quartz Composer plug-in project

XCode автоматически называет файлы с помощью названия проекта, которое Вы предоставляете. Это файлы по умолчанию, предоставленные XCode.

Интерфейсный файл объявляет подкласс 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 и затем Кварцевый Композитор запусков.

Если Вы сделаете какой-либо из следующих, то пользовательские патчи в Вашем плагине не появятся как патчи в Создателе Патча:

Можно проверить, что система входит в систему Консоль для сообщений об ошибках от Кварцевого Композитора.