Ранее были разработаны некоторые элементы пользовательского интерфейса ListBox, RadioBox, Button, CheckBox, Slider. Все это было создано еще на старом Гамаке.
Сейчас GameMkaer "вырос", добавились новые функционалы, и пришла пора модернизировать свои GUI в более современный вид.
|
Для начала создадим родительский элемент/конструктор который будет базисом для всех джочерних элементов и наследовать его.
Так же все события GUI элементов будут транслироваться в EventManager.
====================================================================
Slider Слайдер.
Создаём объект с параметрами:
Скрипт конструктор слайдера:
/// @description SLIDER
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_Slider() : GUIElement() constructor
{
#region Constructor
my_name_is = other.my_name_is;
value = other.value;
old_value = value;
minimum = (min(other.minimum, other.maximum));//floor
maximum = (max(other.minimum, other.maximum));//floor
interval = (clamp(other.interval, minimum, maximum));//floor
tip_x = 0;
//подписка на модификацию данных от внешнего источника
EVENTGUI.subscribe("set_" + my_name_is, function(_data){ set(_data, false); trace("GUI_Slider(", my_name_is,") Получил событие=", "set_", my_name_is, ", данные=", _data);})
EVENTGUI.subscribe("set_random_" + my_name_is, function(){ set_random();})
EVENTGUI.subscribe("set_random_all_sliders", function(){ set_random();})
#endregion
//*******************************************************************
static math_tip_x = function(_val){tip_x = remap(_val, minimum, maximum, _xo, _xo + width);};
//*******************************************************************
static set = function(_value, _flag=true)
{ if is_undefined(_value) then show_message("GUISLIDER _value=undefined");
if !is_undefined(_value)
{ value = clamp(_value,minimum, maximum);// / interval) * interval;
value = (floor(value / interval) * interval)
math_tip_x(value); //расчёт позиции бегунка слайдер
if (old_value != value) and _flag==true then EVENTGUI.publish(my_name_is, value);
old_value = value;
}else value = -1;
}
//*******************************************************************
static set_random = function(){ randomize(); set( random_range(minimum, maximum) );};
//*******************************************************************
static remap = function(val, min1, max1, min2, max2) { return min2 + (max2 - min2) * ((val - min1) / (max1 - min1)); }
//*******************************************************************
static get = function(){return value;}
//*******************************************************************
static listen = function(){ if mouse_grab then set(remap(clamp(mouse_x, _xo, _xo + width), _xo, _xo + width, minimum, maximum)); }
//*******************************************************************
static draw = function()
{ var b;
draw_focus();
if other.slider_type=="BAR" then
{ b=0;// рисуем корпус слайдера корпус
draw_set_color(color_border);
draw_rectangle(_xo, _yo , _xo + width, _yo + height , true);
b=1;
draw_set_color(color_fill); //рисуем саму полоска
if other.slider_draw_button then draw_button(_xo+b, _yo+b, tip_x-b, _yo + height-b, true);
else draw_rectangle(_xo+b, _yo+b, tip_x-b, _yo + height-b, false);
}
if other.slider_type=="BEGUNOK" then
{
b=height/2;
draw_set_color(color_border); // рисуем линию на которой бегает бегунок
if other.slider_draw_button then draw_button(_xo, _yo + b -1 , _xo + width , _yo + b + 1, true);
else draw_rectangle(_xo, _yo + b -1 , _xo + width , _yo + b + 1, false);
draw_set_color(color_fill); //рисуем только бегунок
if other.slider_draw_button then draw_button(tip_x - height/3 , _yo, tip_x + height/3 , _yo + height , true);
else draw_rectangle(tip_x - height/3 , _yo, tip_x + height/3 , _yo + height , false);
}
//рисуем текст
draw_set_hv(fa_left, fa_middle);
draw_set_color(color_text);
draw_set_font(font);
draw_text(_xo + width + padding, _yo + (height * 0.5), string(my_name_is) + ": " + string(get()));
}
//*******************************************************************
//set(value);
math_tip_x(value); //сразу иниции позицию бегунка
}
/// @description Create Slider
slider = new GUI_Slider();
/// @description Step Event Slider
slider.step();
/// @description Draw Event Slider
slider.draw();
====================================================================
SliderHSV Слайдер.
Для проекта ParticleDesigner был создан слайдер выбора цвета в формате HSV.
Добавляем изображение к объекту слайдера:
В наследники ставим объект слайдера обычного.
Но только меняем содержимое события Draw:
draw_self();
slider.draw();
Итоговый объект на экране у нас получится как:
====================================================================
CheckBox.
/// @description CHECK BOX
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_CheckBox() : GUIElement() constructor
{
#region Constructor
my_name_is = other.my_name_is;
value = other.value;
old_value = value; //!value
EVENTGUI.subscribe("set_" + my_name_is, function(_data){ set(_data); trace("GUI_CheckBox(", my_name_is,") Получил событие=", "set_", my_name_is, ", данные=", _data);})
EVENTGUI.subscribe("set_random_" + my_name_is, function(){ set_random();})
EVENTGUI.subscribe("set_random_all_sliders", function(){ set_random();})
#endregion
//*******************************************************************
static set = function(_value, _flag=true)
{ if is_undefined(_value) then show_message("GUICHECKBOX _value=undefined");
value = _value;
if (old_value != value) and (_flag==true) then EVENTGUI.publish(my_name_is, value);
old_value = value;
}
//*******************************************************************
static set_random = function(){ randomize(); set( choose(true,false) );};
//*******************************************************************
static get = function(){return value;}
//*******************************************************************
//static listen = function() { }
//*******************************************************************
static click = function(){ set_focus(); set(!get()); }
//*******************************************************************
static draw = function()
{ draw_focus();
draw_set_color(color_border);
draw_rectangle(x, y, x + height, y + height, false);
if value then draw_set_color(color_fill);
else draw_set_color(color_backgr);
draw_rectangle(x+2, y+2, x + height-2, y + height-2, false);
draw_set_color(color_text);
draw_set_hv(fa_left, fa_middle);
draw_set_font(font);
draw_text(x + height + padding, y + (height * 0.5), my_name_is);
}
//*******************************************************************
//инициализируем значение
//set(value);
//*******************************************************************
}
Объект содержит всего три штатных события со скриптами:
/// @description Create event CheckBox
checkbox = new GUI_CheckBox();
/// @description Step Event CheckBox
checkbox.step();
/// @description DrawEvent CheckBox
checkbox.draw();
Свойства обекта:
Итог:
====================================================================
RadioCheckBox.
Конструктор:
/// @description CHECK BOX
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_RadioBotton() : GUIElement() constructor
{
#region Constructor
my_name_is = other.my_name_is;
value = other.value;
EVENTGUI.subscribe("set_" + my_name_is, function(_data){ set(_data); trace("GUI_RadioBotton(", my_name_is,") Получил событие=", "set_", my_name_is, ", данные=", _data);})
EVENTGUI.subscribe(other.radiobox_group, function(_d) {if _d != _id then { value = false; }})
#endregion
//*******************************************************************
static set = function(_value=true, _flag=true)
{ value = _value;
if _flag==true then EVENTGUI.publish(my_name_is, value);
EVENTGUI.publish(other.radiobox_group, other.id);
}
//*******************************************************************
static get = function(){return value;}
//*******************************************************************
//static listen = function() { }
//*******************************************************************
static click = function() { set_focus(); set(true); }
//*******************************************************************
static draw = function()
{ draw_focus();
draw_set_color(color_border);
draw_circle(x ,y , w2, false);
draw_set_color(color_backgr);
draw_circle(x ,y , w2-2, false);
if value then draw_set_color(color_fill);
else draw_set_color(color_backgr);
draw_circle(x,y , w2-4, false);
draw_set_color(color_text);
draw_set_hv(fa_left, fa_middle);
draw_set_font(font);
draw_text(x + h2 + padding, y , my_name_is);
}
//*******************************************************************
//инициализируем значение
//set(value);
//инициализируем групповую отметку сообщением
EVENTGUI.publish(other.radiobox_group, other.id);
//*******************************************************************
}
Переменная radiobox_group отвечает за группу в которой учавствует checkbox.
Объект check_box содержит следующий код:
/// @description Create Event RadioBox
radiobotton = new GUI_RadioBotton();
/// @description StepEvent RadioBox
radiobotton.step();
/// @description DrawEvent RadioBox
radiobotton.draw();
====================================================================
DropDown.
Конструктор:
/// @description Drop Down
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_DropDown() : GUIElement() constructor
{
//*******************************************************************
#region Constructor
x = other.x;
y = other.y;
my_name_is = other.my_name_is;
options = other.options; //массив пунктов меню
value = other.index; //индекс выделенного пункта меню
#endregion
//*******************************************************************
static set = function(_value, _flag=true)
{ if is_undefined(_value) then {show_message("DROPDOWN set index = undefined"); _value=-1; return;};
value =_value;
if _flag==true then EVENTGUI.publish(my_name_is, [options[value], value]);
}
//*******************************************************************
static listen = function()
{ //ждём клика мышкой
if (!mouse_check_button_pressed(mb_left)) return;
//тогда высчитываем куда ана кликнула
for(var i = array_length(options)-1; i>=0; i--)
{ if (!point_in_rectangle(mouse_x, mouse_y, x, y + (height * (i+1)), x + width, y + (height * (i+2)))) then continue;
set(i); //поймали клик на элементе i
return;
}
}//если мы тут, то кликнули вникуда
//*******************************************************************
static draw = function()
{ var kuku="v";
draw_set_hv(fa_left, fa_middle);
draw_set_font(font);
if (get_focus())
{ kuku= "^";
draw_focus();
draw_set_color(color_text);
for(var i = array_length(options)-1; i>=0; i--)
{ draw_set_color(color_backgr);
if (point_in_rectangle(mouse_x, mouse_y, x, y + (height * (i+1)), x + width, y + (height * (i+2)))) or i==value then draw_set_color(color_fill);
draw_rectangle (x, y + (height * (i+1)), x + width, y + (height * (i+2)), false);
draw_set_color(color_text);
draw_text(x + padding, y + (height * (i+1.5)), options[i]);
}
}
//draw_text(x + width - (padding * 1)-5, y + (height * 0.5), kuku);
draw_set_hv(fa_right, fa_middle);
draw_text(x + width , y + h2, kuku);
//основная часть элемента
draw_set_color(color_border);
draw_rectangle(x, y, x + width, y + height-2, true);
draw_set_color(color_text);
draw_set_hv(fa_left, fa_middle);
draw_text(x + padding, y + h2, options[get()]);
}
//*******************************************************************
//set(value);
//*******************************************************************
}
скрипты объекта:
/// @description Create Event DropDown
checkbox = new GUI_DropDown();
/// @description StepEvent DropDown
checkbox.step();
/// @description Draw Event DropDown
checkbox.draw();
====================================================================
ListBox.
/// @description GUI_ListBox
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_ListBox() : GUIElement() constructor
{
//*******************************************************************
#region Constructor
my_name_is = other.my_name_is;
//items = other.items; //массив пунктов меню
value = other.index; //индекс выделенного пункта меню
old_depth = other.depth; //стоковая глубина элемента
//for (var i = 0; i < 4; i++) other.items[i] = string(random(100));
lowerPos = 0;
max_column_display = floor(height / char_height);
GUI_Elements.add_element(my_name_is, self);
#endregion
static set_focus = function() {focus = true; other.depth -= 10;}
//*******************************************************************
static remove_focus = function() {focus = false; other.depth = old_depth;}
//*******************************************************************
static add_item = function(_item){ array_push(other.items, _item); }
//*******************************************************************
EVENTGUI.subscribe("add_item_" + my_name_is, function(_item){ add_item(_item); trace("GUI_ListBox(", my_name_is,") Получил событие=", "add_item_", my_name_is, ", данные=", _item);})
//*******************************************************************
static set = function(_value, _flag=true)
{ if is_undefined(_value) then {show_message("ListBox set index = undefined"); _value=-1; return;};
value =_value;
if _flag==true then
{ EVENTGUI.publish(my_name_is, [other.items[value], value]);
if callback!=pointer_null then callback([other.items[value], value]);}
}
//*******************************************************************
static listen = function()
{
if (get_focus())
{ //перемещение списка вниз(к началу)
if (mouse_wheel_up()) then{ lowerPos = max(lowerPos-1, 0)};
else //перемещение списка вверх(к концу)
if (mouse_wheel_down()) then{ if lowerPos < (array_length(other.items) - max_column_display) then lowerPos = lowerPos+1;};
}
//ждём клика мышкой
if (!mouse_check_button_pressed(mb_left)) return;
//очистка состояния кнопок мыши, что бы други элементы ГУИ под курсором не схавали это событие
//можно создать событие приоритета элементов, где он отключает реакции других элементов на мыщку
mouse_clear(mb_any);
//тогда высчитываем куда ана кликнула
for(var i = 0; i< max_column_display; i++)
{ var pos = lowerPos + i;
if pos>=array_length(other.items) then break;
if (!point_in_rectangle(mouse_x, mouse_y, x, y + (char_height * (i+0)), x + width, y + (char_height * (i+1)))) then continue;
set(pos); //поймали клик на элементе pos
return;
}
}//если мы тут, то кликнули вникуда
//*******************************************************************
static draw = function()
{ //var kuku="v";
draw_set_hv(fa_left, fa_middle);
draw_set_font(font);
draw_focus();
//if (get_focus())
{
oldd = other.depth;
other.depth-=10;
draw_set_color(color_text);
for(var i = 0; i< max_column_display; i++)
{
var pos = lowerPos + i;
if pos>=array_length(other.items) then break;
draw_set_color(color_backgr);
//if (point_in_rectangle(mouse_x, mouse_y, x, y + (char_height * (i+1)), x + width, y + (char_height * (i+2)))) or pos==get() then draw_set_color(color_fill);
if pos==get() then draw_set_color(color_fill);
//draw_rectangle (x, y + (char_height * (i+1)), x + width, y + (char_height * (i+2)), false);
draw_rectangle (x, y + (char_height * (i+0)), x + width, y + (char_height * (i+1)), false);
draw_set_color(color_text);
draw_text(x + padding, y + (char_height * (i+0.5)), other.items[pos]);
}
other.depth=oldd;
}
}
//*******************************************************************
//set(value);
//*******************************************************************
}
====================================================================
Slider vertical.
/// @description SLIDER
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_SliderV() : GUIElement() constructor
{
#region Constructor
my_name_is = other.my_name_is;
value = other.value;
old_value = value;
minimum = (min(other.minimum, other.maximum));//floor
maximum = (max(other.minimum, other.maximum));//floor
interval = (clamp(other.interval, minimum, maximum));//floor
tip_y = 0;//other.x;
GUI_Elements.add_element(my_name_is, self);
//подписка на модификацию данных от внешнего источника
EVENTGUI.subscribe("set_" + my_name_is, function(_data){ set(_data, false); trace("GUI_Slider(", my_name_is,") Получил событие=", "set_", my_name_is, ", данные=", _data);})
EVENTGUI.subscribe("set_random_" + my_name_is, function(){ set_random();})
EVENTGUI.subscribe("set_random_all_sliders", function(){ set_random();})
#endregion
//*******************************************************************
static math_tip_y = function(_val)
{ tip_y = remap(_val, minimum, maximum, _yo + height, _yo );
};
//*******************************************************************
static set = function(_value, _flag=true)
{ if is_undefined(_value) then show_message("GUISLIDER _value=undefined");
if !is_undefined(_value)
{ value = clamp(_value,minimum, maximum);// / interval) * interval;
value = (floor(value / interval) * interval)
math_tip_y(value); //расчёт позиции бегунка слайдер
if (old_value != value) and _flag==true then EVENTGUI.publish(my_name_is, value);
old_value = value;
if callback!=pointer_null then callback(value);
}else value = -1;
}
//*******************************************************************
static set_random = function(){ randomize(); set( random_range(minimum, maximum) );};
//*******************************************************************
static remap = function(val, min1, max1, min2, max2) { return min2 + (max2 - min2) * ((val - min1) / (max1 - min1)); }
//*******************************************************************
static get = function(){return value;}
//*******************************************************************
static listen = function(){ if mouse_grab then set(remap(clamp(mouse_y, _yo, _yo + height), _yo + height, _yo , minimum, maximum)); }
//*******************************************************************
static draw = function()
{ var b;
draw_focus();
if other.slider_type=="BAR" then
{ b=0;// рисуем корпус слайдера корпус
draw_set_color(color_border);
draw_rectangle(_xo, _yo , _xo + width, _yo + height , true);
b=1;
draw_set_color(color_fill); //рисуем саму полоска
if other.slider_draw_button then draw_button(_xo - b + width-1, tip_y, _xo+b+1, _yo-b+height, true);
else draw_rectangle(_xo - b + width, tip_y, _xo+b, _yo-b+height, false);
}
if other.slider_type=="BEGUNOK" then
{
//b=height/2;
b=width/2;
draw_set_color(color_border); // рисуем линию на которой бегает бегунок
if other.slider_draw_button then draw_button(_xo + b - 1, _yo , _xo +b + 1, _yo + height, true);
else draw_rectangle(_xo + b - 1, _yo , _xo +b + 1, _yo + height, false);
draw_set_color(color_fill); //рисуем только бегунок
if tip_y < _yo then tip_y=_yo;//исправляет, глюк, бегунок при старте экрана находится где хрен знает где но не на слайдере почемуто
if other.slider_draw_button then draw_button(_xo, tip_y - width/3 , _xo + width, tip_y + width/3 , true);
else draw_rectangle(_xo, tip_y - width/3 , _xo + width, tip_y + width/3 , false);
}
//рисуем текст
draw_set_hv(fa_center, fa_middle);
draw_set_color(color_text);
draw_set_font(font);
draw_text(_xo + width, _yo + (height * 1) + padding+5, string(my_name_is) + ": " + string(get()));
}
//*******************************************************************
//set(value);
math_tip_y(value); //сразу иниции позицию бегунка
}
====================================================================
CircularSlider Круговой Слайдер.
/// @description
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_KnobCircular() : GUIElement() constructor
{
#region Constructor
my_name_is = other.my_name_is;
angle = other.image_angle + other.angle; //градусы 0-360
pointinrect = false; //детект мыши по окружности а не по прямоугольнику
GUI_Elements.add_element(my_name_is, self);
#endregion
//*******************************************************************
//значение other.angle_speed должно быть > 5 иначе регулятор двигаеться не будет.
//прилипание к целым значения градусов
static prilipalka = function(a)
{
var f = min(other.angle_speed, 5);
if a>360-f then return 360;
if a<f then return 0;
if a>(45-f) and a<(45+f) then return 45;
if a>(90-f) and a<(90+f) then return 90;
if a>(135-f) and a<(135+f) then return 135;
if a>(180-f) and a<(180+f) then return 180;
if a>(225-f) and a<(225+f) then return 225;
if a>(270-f) and a<(270+f) then return 270;
if a>(315-f) and a<(315+f) then return 315;
return a;
}
//*******************************************************************
static set = function(a)
{ a = clamp(a, 0,360);
a = prilipalka(a);
other.image_angle = a + other.offset_degree;
if a != angle then
{ angle = a;
EVENTGUI.publish(my_name_is, a);
if callback!=pointer_null then callback(value);
}
}
//*******************************************************************
static listen = function()
{ if mouse_grab then
{ var targetDirection = point_direction(x, y, mouse_x, mouse_y);
var angleDifference = angle_difference(angle+ other.offset_degree, targetDirection);
var angleIncrement = other.angle_speed; //скорость перемещения угла к конечному результату
var a = angle - (min(abs(angleDifference), angleIncrement) * sign(angleDifference));
set(a);
};
}
//*******************************************************************
static draw = function()
{
with(other){draw_self();};
draw_set_hv();
draw_set_color(color_text);
draw_text(x,y+height/2 + padding+4,my_name_is + string(floor(angle)))
draw_focus();
};
//*******************************************************************
set(angle);
}
====================================================================
VolumSlider Круговой Слайдер по типу регулятора громкости.
/// @description
//Site: MidaDev.ru
//Author: Dimusikus
function GUI_KnobVolume() : GUIElement() constructor
{
#region Constructor
my_name_is = other.my_name_is;
angle = other.image_angle + volume_to_angle(other.volume); //градусы 0-360
pointinrect = false; //детект мыши по окружности а не по прямоугольнику
GUI_Elements.add_element(my_name_is, self);
#endregion
//*******************************************************************
///Map(val, min1, max1, min2, max2)
static remap = function(val, min1,max1, min2, max2)
{
return min2 + (max2 - min2) * ((val - min1) / (max1 - min1));
}
//*******************************************************************
//angle to volume
static angle_to_volume = function(_angle)
{
return remap(_angle, other.angle_min , other.angle_max, 1, 0);
}
//*******************************************************************
//volume to angle
static volume_to_angle = function(_vol)
{
return remap(_vol, 0, 1, other.angle_min, other.angle_max);
}
//*******************************************************************
static set = function(a)
{ a = clamp(a, other.angle_min, other.angle_max);
other.image_angle = a + other.offset_degree;
if a != angle then
{ angle = a;
other.volume = angle_to_volume(angle);
EVENTGUI.publish(my_name_is, other.volume);
if callback!=pointer_null then callback(other.volume);
}
}
//*******************************************************************
static listen = function()
{ if mouse_grab then
{ var targetDirection = point_direction(x, y, mouse_x, mouse_y);
var angleDifference = angle_difference(angle+ other.offset_degree, targetDirection);
var angleIncrement = other.angle_speed; //скорость перемещения угла к конечному результату
var a = angle - (min(abs(angleDifference), angleIncrement) * sign(angleDifference));
set(a);
};
}
//*******************************************************************
static draw = function()
{
with(other)
{
draw_sprite_ext(sprite_index, 0, x, y, image_xscale, image_yscale, 0, image_blend, image_alpha);
draw_sprite_ext(sprite_index, 1, x, y, image_xscale, image_yscale, image_angle, image_blend, image_alpha);
//draw_self();
};
draw_set_hv();
draw_set_color(color_text);
draw_text(x,y+height/2 + padding+4,my_name_is + string(other.volume))
draw_focus();
};
//*******************************************************************
set(angle);
}