• Уважаемые гости и новички, приветствуем Вас на нашем форуме
    Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!

:Туториал по созданию многостраничного документа

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
Туториал по созданию многостраничного документа, а также кое-чего ещё.

Собственно говоря, приступим к делу.
С чего же началось написание этого тутора. В принципе, я не планировал делать книги «на несколько страниц», ибо не было серьёзной причины и наличия в моде книг, развернутых на несколько страниц текста. Но, случайно изучая предметы готики, наткнулся на такую вещь, как «Факел», но не тот факел, что обычно использует ГГ, а тот, что использовали артисты на помосте, выдувая пламя изо рта. Что же в нем такого особенного? А то, что имеет он 5 состояний (с 0-го по 4-й), ибо в скриптах – в расписании этих артистов идёт использование этого факела до 5-го состояния (хотя, достаточно и до 4-го):
Код:
[COLOR="Blue"]func int[/COLOR] ZS_Spit_Fire_loop()
{
	[COLOR="#0000ff"]if[/COLOR](Wld_IsFPAvailable([COLOR="SandyBrown"]self[/COLOR],"STAND"))
	{
		AI_GotoFP([COLOR="#f4a460"]self[/COLOR],"STAND");
		AI_AlignToFP([COLOR="#f4a460"]self[/COLOR]);
	}
	[COLOR="#0000ff"]else[/COLOR]
	{
		AI_AlignToWP([COLOR="#f4a460"]self[/COLOR]);
	};
	[COLOR="#0000ff"]if[/COLOR](Npc_GetStateTime(self) > 10)
	{
		AI_UseItemToState([COLOR="#f4a460"]self[/COLOR],ItLsTorchFirespit,5);
		AI_UseItemToState([COLOR="#f4a460"]self[/COLOR],ItLsTorchFirespit,0);
		Npc_SetStateTime([COLOR="#f4a460"]self[/COLOR],0);
	};
	[COLOR="#0000ff"]return[/COLOR] LOOP_CONTINUE;
};
Об этом свидетельствует и mds-скрипт анимации взаимодействия с этим факелом:
// Feuerspucken
ani ("t_FIRESPIT_Stand_2_S0" 1 "s_FIRESPIT_S0" 0.2 0.0 M. "Hum_FireSpit_M01.asc" F 0 69 FPS:10)
{
*eventTag (1 "DEF_INSERT_ITEM" "ZS_RIGHTHAND")
*eventTag (1 "DEF_CREATE_ITEM" "ZS_LEFTHAND" "ItLsTorch")​
}
ani ("s_FIRESPIT_S0" 1 "s_FIRESPIT_S0" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 70 70)
ani ("t_FIRESPIT_S0_2_Stand" 1 "" 0.0 0.1 M. "Hum_FireSpit_M01.asc" R 0 69 FPS:10)
{
*eventTag (1 "DEF_REMOVE_ITEM")​
}
ani ("t_FIRESPIT_S0_2_S1" 1 "s_FIRESPIT_S1" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 71 126 FPS:10)
{
*eventSFX (80 "SPIT_FIRE" R:1000 EMPTY_SLOT)
*eventPFX (83 1 "FLAMETHROWER" "BIP01 HEAD" ATTACH)
*eventPFXStop (100 1)​
}
ani ("s_FIRESPIT_S1" 1 "s_FIRESPIT_S1" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 127 127)
ani ("t_FIRESPIT_S1_2_S2" 1 "s_FIRESPIT_S2" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 128 160 FPS:10)
{
*eventSFX (139 "SPIT_FIRE" R:1000 EMPTY_SLOT)
*eventPFX (140 1 "FLAMETHROWER" "BIP01 HEAD" ATTACH)
*eventPFXStop (155 1)​
}
ani ("s_FIRESPIT_S2" 1 "s_FIRESPIT_S2" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 161 161)
ani ("t_FIRESPIT_S2_2_S3" 1 "s_FIRESPIT_S3" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 162 195 FPS:10)
{
*eventSFX (170 "SPIT_FIRE" R:1000 EMPTY_SLOT)
*eventPFX (171 1 "FLAMETHROWER" "BIP01 HEAD" ATTACH)
*eventPFXStop (180 1)​
}
ani ("s_FIRESPIT_S3" 1 "s_FIRESPIT_S3" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 196 196)
ani ("t_FIRESPIT_S3_2_S4" 1 "s_FIRESPIT_S4" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 197 229 FPS:10)
{
*eventSFX (204 "SPIT_FIRE" R:1000 EMPTY_SLOT)
*eventPFX (205 1 "FLAMETHROWER" "BIP01 HEAD" ATTACH)
*eventPFXStop (220 1)​
}
ani ("s_FIRESPIT_S4" 1 "s_FIRESPIT_S4" 0.0 0.0 M. "Hum_FireSpit_M01.asc" F 230 230)
ani ("t_FIRESPIT_S4_2_Stand" 1 "" 0.0 0.1 M. "Hum_FireSpit_M01.asc" F 230 240)
{
*eventTag (239 "DEF_REMOVE_ITEM")​
}
Так, а теперь остановимся на манипулировании сразу более-менее сложными вещами и перейдём к изучению по порядку. Что же мы имеем вначале:
- идея, создать документ с возможностью просмотра более 1 страницы.
Как у нас выглядит стандартный листок бумаги, который мы встречаем в игре. Пример, список трав Константино:
Код:
[COLOR="#0000ff"]instance[/COLOR] ItWr_Kraeuterliste(C_Item)
{
	name = "Список";
	mainflag = ITEM_KAT_DOCS;
	flags = ITEM_MISSION;
	value = 0;
	visual = "ItWr_Scroll_01.3DS";
	material = MAT_LEATHER;
	[b]on_state[0][/b] = Use_Kraeuterliste;
	[b]scemeName[/b] = "MAP";
	description = "Список трав Константино.";
};
[COLOR="#0000ff"]func void[/COLOR] Use_Kraeuterliste()
{
	[COLOR="#0000ff"]var int[/COLOR] nDocID;
	nDocID = Doc_Create();
	Doc_SetPages(nDocID,1);
	Doc_SetPage(nDocID,0,"letters.TGA",0);
	Doc_SetFont(nDocID,-1,FONT_Book);
	Doc_SetMargins(nDocID,-1,50,50,50,50,1);
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"Алхимические травы");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"Лечебная трава");
	Doc_PrintLine(nDocID,0,"Лечебное растение");
	Doc_PrintLine(nDocID,0,"Лечебный корень");
	Doc_PrintLine(nDocID,0,"Огненная крапива");
	Doc_PrintLine(nDocID,0,"Огненная трава");
	Doc_PrintLine(nDocID,0,"Огненный корень");
	Doc_PrintLine(nDocID,0,"Гоблинские ягоды");
	Doc_PrintLine(nDocID,0,"Драконий корень");
	Doc_PrintLine(nDocID,0,"Снеппер-трава");
	Doc_PrintLine(nDocID,0,"Луговой горец");
	Doc_PrintLine(nDocID,0,"Царский щавель");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLines(nDocID,0,"Примечание: Пусть кандидат... ");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"С уважением, Зурис.");
	Doc_SetMargins(nDocID,-1,200,50,50,50,1);
	Doc_Show(nDocID);
};
Обратите внимание на выделенные фрагменты:
Scemename = "MAP";
On_state[0] = Use_Kraeuterliste;
Что же такое scemename? Это название набора анимаций для взаимодействия с предметом или объектом мира.
В частности для нашего документа, что это? Открываем mds-скрипт анимаций человека humans.mds и ищем что-то содержащее слово MAP… ага, вот:
// Schriftrolle lesen
ani ("t_MAP_Stand_2_S0" 1 "s_MAP_S0" 0.1 0.0 M. "Hum_MapRead_M01.asc" F 1 24)
{
*eventTag (18 "DEF_INSERT_ITEM" "ZS_RIGHTHAND")
*eventSFX (18 "Scroll_Unfold")​
}
ani ("s_MAP_S0" 1 "s_MAP_S0" 0.0 0.0 M. "Hum_MapRead_M01.asc" F 25 25)
ani ("t_MAP_S0_2_Stand" 1 "" 0.0 0.1 M. "Hum_MapRead_M01.asc" R 1 24)
{
*eventTag (18 "DEF_REMOVE_ITEM")
*eventSFX (18 "Map_Unfold" R:1000)​
}
Я думаю за разъяснением этих строк вам можно обратиться к туторам Vam’a и Kerrax’а.
Вот: Динамическая модель (3DS Max, анимация и меши)
И вот: Динамическая модель: описание eventTag'ов
От себя поясню. Видите, что упомянутое в скрипте слово «MAP» фигурирует здесь в таком вот виде:
T_MAP_Stand_2_S0 , S_MAP_S0, T_MAP_S0_2_Stand.
Что же это:
  • T_MAP_Stand_2_S0 – это переход из состояния «Стою» в нулевое состояние взаимодействия с предметом, (в нашем случае – список), и какая при этом проигрывается анимация.
  • S_MAP_S0 – это пребывание человека в нулевом состоянии, и какая при этом проигрывается анимация.
  • T_MAP_S0_2_Stand – это переход из нулевого состояния в состояние «Стою».
Как мы видим, и это подтверждается на деле в игре, при открытии инвентаря и нажатия кнопки «Действие» на предмете «Список трав константино», ГГ производит следующие действия:
  1. Герою в руку помещается свиток, и он воспроизводит анимацию перехода в режим чтения.
  2. ГГ стоит и читает листок – всего лишь 1 кадр;
  3. ГГ убирает предмет-список в инвентарь – перед этим на экран выводится текст записки.
Всё очень просто, но к чему я всё это объясняю, где эта многостраничность. Идём далее, рассмотрим второй выделенный жирным фрагмент:
On_state[0] = Use_Kraeuterliste;
Поясняю – применительно к предметам инвентаря, это означает ту функцию, которая будет вызвана при выходе, подчеркиваю при выходе из 0-го состояния (если on_state[1] – то функция сработает при выходе из 1-го состояния). В нашем случае, это вывод текста записки на экран.
Чтож истина где-то рядом, но ещё не близко.
Продолжим рассуждение, которое я буду сопровождать пояснением. Значит, делая вывод и всего вышеизложенного, чтобы вывести например текст второй записки на экран, нам надо следующее, нам надо создать функцию, которая выведет на экран текст второй записки. Так, если первая записка вывелась на экран при выходе из 0-го состояния, значит, текст второй записки можно вывести на экран при выходе из 1-го состояния. Всё логично.
Теперь подключаем мозг и учимся думать и применять эмпирический путь для поиска истины.
По аналогии создадим функцию: On_state[1] = Use_ Kraeuterliste_1;
Код:
[COLOR="#0000ff"]func void[/COLOR] Use_Kraeuterliste_1()
{
	[color="#0000ff"]var int[/COLOR] nDocID;
	nDocID = Doc_Create();
	Doc_SetPages(nDocID,1);
	Doc_SetPage(nDocID,0,"letters.TGA",0);
	Doc_SetFont(nDocID,-1,FONT_Book);
	Doc_SetMargins(nDocID,-1,50,50,50,50,1);
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"Алхимические травы");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLines(nDocID,0,"Примечание: Пусть кандидат... ");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"С уважением, Зурис.");
	Doc_SetMargins(nDocID,-1,200,50,50,50,1);
	Doc_Show(nDocID);
};
Но не тут то было, даже если мы произведем все нижеуказанные действия, касающиеся анимации, это не выведет на экран текст второй записки, он появится позади этой запиской, ибо в это время на экран выведен первый документ. Следовательно, чтобы в этот момент на экране в той же записке появился другой текст, нам надо заменить текущий текст на тот, что во второй записке. Тааак-с. Давайте исследуем первую функцию, а именно начало и конец:
var int nDocID;
nDocID = Doc_Create();

Doc_Show(nDocID);
Это тот набор функций, отвечающий за создание документа и вывода его на экран (всё можно посмотреть в туторе Vam’а касательно скриптов)
Следовательно, опять подключаем мозг… Делаем вывод, нам не нужно создавать второй документ, а надо изменить первосозданный. Делаем следующее:
Код:
[COLOR="#0000ff"]instance[/COLOR] ItWr_Kraeuterliste(C_Item)
{
	name = "Список";
	mainflag = ITEM_KAT_DOCS;
	flags = ITEM_MISSION;
	value = 0;
	visual = "ItWr_Scroll_01.3DS";
	material = MAT_LEATHER;
	[b]on_state[0][/b] = Use_Kraeuterliste;
	[b]on_state[1][/b] = Use_Kraeuterliste_1;
	[b]scemeName[/b] = "MAP";
	description = "Список трав Константино.";
};
[COLOR="#0000ff"]var int[/COLOR] nDocID;
[COLOR="#0000ff"]func void[/COLOR] Use_Kraeuterliste()
{
	nDocID = Doc_Create();
	Doc_SetPages(nDocID,1);
	Doc_SetPage(nDocID,0,"letters.TGA",0);
	Doc_SetFont(nDocID,-1,FONT_Book);
	Doc_SetMargins(nDocID,-1,50,50,50,50,1);
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"Алхимические травы");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"Лечебная трава");
	Doc_PrintLine(nDocID,0,"Лечебное растение");
	Doc_PrintLine(nDocID,0,"Лечебный корень");
	Doc_PrintLine(nDocID,0,"Огненная крапива");
	Doc_PrintLine(nDocID,0,"Огненная трава");
	Doc_PrintLine(nDocID,0,"Огненный корень");
	Doc_PrintLine(nDocID,0,"Гоблинские ягоды");
	Doc_PrintLine(nDocID,0,"Драконий корень");
	Doc_PrintLine(nDocID,0,"Снеппер-трава");
	Doc_PrintLine(nDocID,0,"Луговой горец");
	Doc_PrintLine(nDocID,0,"Царский щавель");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLines(nDocID,0,"Примечание: Пусть кандидат... ");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"С уважением, Зурис.");
	Doc_SetMargins(nDocID,-1,200,50,50,50,1);
	Doc_Show(nDocID);
};
[COLOR="#0000ff"]func void[/COLOR] Use_Kraeuterliste_1()
{
	Doc_SetPages(nDocID,1);
	Doc_SetPage(nDocID,0,"letters.TGA",0);
	Doc_SetFont(nDocID,-1,FONT_Book);
	Doc_SetMargins(nDocID,-1,50,50,50,50,1);
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"Алхимические травы");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLines(nDocID,0,"Примечание: Пусть кандидат... ");
	Doc_PrintLine(nDocID,0,"");
	Doc_PrintLine(nDocID,0,"С уважением, Зурис.");
	Doc_SetMargins(nDocID,-1,200,50,50,50,1);
};

Чтоб не натыкаться на грабли, сразу внесем дополнения в файл humans.mds . Нам же нужны переходы в 1-е состояние.
ani ("t_MAP_Stand_2_S0" 1 "s_MAP_S0" 0.1 0.0 M. "Hum_MapRead_M01.asc" F 1 24)
{
*eventTag (18 "DEF_INSERT_ITEM" "ZS_RIGHTHAND")
*eventSFX (18 "Scroll_Unfold")​
}
ani ("s_MAP_S0" 1 "s_MAP_S0" 0.0 0.0 M. "Hum_MapRead_M01.asc" F 25 25)
ani ("t_MAP_S0_2_Stand" 1 "" 0.0 0.1 M. "Hum_MapRead_M01.asc" R 1 24)
{
*eventTag (18 "DEF_REMOVE_ITEM")
*eventSFX (18 "Map_Unfold" R:1000)​
}
ani ("t_MAP_S0_2_S1" 1 "s_MAP_S1" 0.1 0.0 M. "Hum_MapRead_M01.asc" F 1 24)
{
*eventSFX (18 "Scroll_Unfold")​
}
ani ("s_MAP_S1" 1 "s_MAP_S1" 0.0 0.0 M. "Hum_MapRead_M01.asc" F 25 25)
ani ("t_MAP_S1_2_S0" 1 "" 0.0 0.1 M. "Hum_MapRead_M01.asc" R 1 24)
{
*eventSFX (18 "Map_Unfold" R:1000)​
}
ani ("t_MAP_S1_2_Stand" 1 "" 0.0 0.1 M. "Hum_MapRead_M01.asc" R 1 24)
{
*eventTag (18 "DEF_REMOVE_ITEM")
*eventSFX (18 "Map_Unfold" R:1000)​
}
Что мы теперь имеем: мы имеем функции, которые выведут на экран две записки, мы имеем анимации для перехода в 0-е и 1-е состояния и выхода из них, следовательно переносим это всё дело в файлы готы. Как?
Учимся на mod.worldofgothic.ru
Если вы всё скомпилировали и вставили в игру, то пробуем:
Открываем инвентарь, нажимаем на свиток… что ж вывелся текст и всё? А где же вторая записка?
Поясняю. при простом нажатии кнопки действия на предмете инвентаря – это касается вещей, которые не экипируются и у которых имеется взаимодействие: еда, документы, - предмет перводится в 0-е состояние и обратно. Чтобы перевести предмет в 1-е состояние, надо сделать следующее:
  • А) Зажать (! Не нажать !) кнопку «Дествие» на предмете (переведётся в 0-е состояние) и нажать кнопку «Вперед» (переведётся в 1-е состояние) – выведется первая записка на экран.
  • Б) Просто отпускаем кнопку «Действие» (перейдёт из 1-го состояния в состояние «Стою») – выведется на экран текст второй записки.

P.S.
К сожалению, этот способ имеет свое ограничение. Массив on_state имеет максимальный размер – 4 элемента: с 0-го по 3-й; то есть можно использовать переходы вплоть до 3-го состояния. Но, честно говоря, книжные тома, развернутые на бОльшее пространство, читать вряд ли кто-то будет. Да, и вариант листать "вперёд-назад" здесь не канает. Не скажу, что это единственный способ получения многостраничных документов (есть варианты как на базе оригинального набора инструментов Готики, так и с помощью G2Ext), но как вариант – пойдёт.
А ещё, самое главное, по аналогии можно реализовать какие-нибудь интересные вещи, типа «Употреблять еду за 4 укуса» :) Дерзайте!

За сим откланиваюсь.*flowers*
 

Вариматас

Забанен
Регистрация
11 Апр 2011
Сообщения
175
Благодарности
1
Баллы
165
Хороший вариант, но думаю с г2екстом можно сделать немного проще, тк там можно выводить ЛЮБОЕ изображение на экран, и по верх него писать нужный текст, а для переклюения страниц можно сделать просто кнопки "вперед" назад, но как ты уже сказал как вариант - норм)
 

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
435
Благодарности
261
Баллы
230
Мне кажется будет не очень удобно читать с нажатой кнопкой...
Есть другой вариант реализации(как чтения документа, так и записи в него), но там пока что есть косяк, который придётся обходить через лес и через горы...

Про сам урок могу сказать, что полезный всем, т.к. вспоминаются многие вещи.
Жаль, что не очень удобная реализация по описанию...
 

Вариматас

Забанен
Регистрация
11 Апр 2011
Сообщения
175
Благодарности
1
Баллы
165
Мне кажется будет не очень удобно читать с нажатой кнопкой...
Есть другой вариант реализации(как чтения документа, так и записи в него), но там пока что есть косяк, который придётся обходить через лес и через горы...

Про сам урок могу сказать, что полезный всем, т.к. вспоминаются многие вещи.
Жаль, что не очень удобная реализация по описанию...
Какой такой вариант? На Икарусе чтоли? Или на чем? Если сказал, то будь добр описать то что говоришь...
 

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.371
Благодарности
7.800
Баллы
995
Вариматас, Да, на Икарусе реализван был один многостраничник, уже как года 3 назад. Спинер писал если не ошибаюсь. Правда не знаю, о нем ли речь. ::)
 

Вариматас

Забанен
Регистрация
11 Апр 2011
Сообщения
175
Благодарности
1
Баллы
165
Это я знаю) Я читал тот пост спинера, думаю может тут новый Велик придумали=)

Bump: Зы Вообще можно и тупо без всяких извратов сделать книгу на несколько страниц, только они будут показаны все на экране);)
 

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
435
Благодарности
261
Баллы
230
Какой такой вариант? На Икарусе чтоли? Или на чем? Если сказал, то будь добр описать то что говоришь...

Расписывать этот вариант я тут не буду. Всё делается в обычном режиме с элементами длительного описания. Даже если оно надо было бы кому-то, то:
1) До конца данная возможность не реализована по времени, но на стадии завершения(есть некоторые косяки в плане открытия документов).
2) Не хватит текстового поля чтобы описать всё.

Попрошу не приставать ко мне с этим вопросом. Пожалуйста:) Может быть кому-то показалось, что я хвалился, когда написал мысль? Нет, на самом деле это похоже на прохождение через заросли возможностей движка...
 

Вариматас

Забанен
Регистрация
11 Апр 2011
Сообщения
175
Благодарности
1
Баллы
165
Мм, понятно все) У мну есть идея немного похожей реализации(думаю мы говорим об одном и томже=)) Мой вариант тупо ставить нужные тексты записывать в константу, и потом просто менять ее в функциях принт лайнс, в докуметах, можно повеить на клавиши P и H
 

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
Мм, понятно все) У мну есть идея немного похожей реализации(думаю мы говорим об одном и томже=)) Мой вариант тупо ставить нужные тексты записывать в константу, и потом просто менять ее в функциях принт лайнс, в докуметах, можно повеить на клавиши P и H
Эти клавиши не работают в момент вывода документа на экран, иначе бы этот способ тоже висел здесь.
 

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
435
Благодарности
261
Баллы
230
У кого есть мысли на счёт того как можно закрыть открытый документ не дотрагиваясь до клавиатуры и мышки?
Reset тоже не трогать:)
... что может прервать чтение документа?
Если нету вариантов, игнорируем данный пост.
 

Вариматас

Забанен
Регистрация
11 Апр 2011
Сообщения
175
Благодарности
1
Баллы
165
По идеи фаза анимации, или чтот вроди того, хотя.. по моему анрил...
Эти клавиши не работают в момент вывода документа на экран, иначе бы этот способ тоже висел здесь.
Дак и что? Г2екст вам в помощь....
 
Сверху Снизу