示例#1
0
void ProgressBar::_notification(int p_what) {


	if (p_what==NOTIFICATION_DRAW) {

		Ref<StyleBox> bg = get_stylebox("bg");
		Ref<StyleBox> fg = get_stylebox("fg");
		Ref<Font> font = get_font("font");
		Color font_color=get_color("font_color");
		Color font_color_shadow=get_color("font_color_shadow");

		draw_style_box(bg,Rect2(Point2(),get_size()));
		float r = get_unit_value();
		int mp = fg->get_minimum_size().width;
		int p = r*get_size().width-mp;
		if (p>0) {

			draw_style_box(fg,Rect2(Point2(),Size2(p+fg->get_minimum_size().width,get_size().height)));
		}

		int fh=font->get_height();
		String txt=itos(int(get_unit_value()*100))+"%";
		font->draw_halign(get_canvas_item(),Point2(0,font->get_ascent()+(get_size().height-font->get_height())/2),HALIGN_CENTER,get_size().width,txt,font_color);
	}
}
示例#2
0
void ReferenceFrame::_notification(int p_what) {

	if (p_what==NOTIFICATION_DRAW) {

		if (!is_inside_scene())
			return;
		if (get_scene()->is_editor_hint())
			draw_style_box(get_stylebox("border"),Rect2(Point2(),get_size())) ;
	}
}
示例#3
0
void GraphNode::_notification(int p_what) {

	if (p_what==NOTIFICATION_DRAW) {

		Ref<StyleBox> sb=get_stylebox("frame");
		Ref<Texture> port =get_icon("port");
		Ref<Texture> close =get_icon("close");
		int close_offset = get_constant("close_offset");
		Ref<Font> title_font = get_font("title_font");
		int title_offset = get_constant("title_offset");
		Color title_color = get_color("title_color");
		Point2i icofs = -port->get_size()*0.5;
		int edgeofs=get_constant("port_offset");
		icofs.y+=sb->get_margin(MARGIN_TOP);
		draw_style_box(sb,Rect2(Point2(),get_size()));

		int w = get_size().width-sb->get_minimum_size().x;

		if (show_close)
			w-=close->get_width();

		draw_string(title_font,Point2(sb->get_margin(MARGIN_LEFT),-title_font->get_height()+title_font->get_ascent()+title_offset),title,title_color,w);
		if (show_close) {
			Vector2 cpos = Point2(w+sb->get_margin(MARGIN_LEFT),-close->get_height()+close_offset);
			draw_texture(close,cpos);
			close_rect.pos=cpos;
			close_rect.size=close->get_size();
		} else {
			close_rect=Rect2();
		}

		for (Map<int,Slot>::Element *E=slot_info.front();E;E=E->next()) {

			if (E->key() < 0 || E->key()>=cache_y.size())
				continue;
			if (!slot_info.has(E->key()))
				continue;
			const Slot &s=slot_info[E->key()];
			//left
			if (s.enable_left)
				port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left);
			if (s.enable_right)
				port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right);

		}
	}

	if (p_what==NOTIFICATION_SORT_CHILDREN) {

		_resort();
	}

}
示例#4
0
void RichTextLabel::_notification(int p_what) {

	switch (p_what) {

		case NOTIFICATION_RESIZED: {

			main->first_invalid_line=0; //invalidate ALL
			update();

		} break;
		case NOTIFICATION_ENTER_TREE: {

			set_bbcode(bbcode);
			main->first_invalid_line=0; //invalidate ALL
			update();

		} break;
		case NOTIFICATION_THEME_CHANGED: {

			if (is_inside_tree() && use_bbcode) {
				parse_bbcode(bbcode);
				//first_invalid_line=0; //invalidate ALL
				//update();
			}

		} break;
		case NOTIFICATION_DRAW: {

			_validate_line_caches(main);
			_update_scroll();


			RID ci=get_canvas_item();
			Size2 size = get_size();

			VisualServer::get_singleton()->canvas_item_set_clip(ci,true);

			if (has_focus()) {
				VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci,true);
				draw_style_box(get_stylebox("focus"),Rect2(Point2(),size));
				VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci,false);
			}

			int ofs = vscroll->get_val();

			//todo, change to binary search

			int from_line = 0;
			int total_chars = 0;
			while (from_line<main->lines.size()) {

				if (main->lines[from_line].height_accum_cache>=ofs)
					break;
				from_line++;
				total_chars+=main->lines[from_line].char_count;
			}

			if (from_line>=main->lines.size())
				break; //nothing to draw

			int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs;
			Ref<Font> base_font=get_font("normal_font");
			Color base_color=get_color("default_color");

			while (y<size.height && from_line<main->lines.size()) {

				_process_line(main,Point2(),y,size.width-scroll_w,from_line,PROCESS_DRAW,base_font,base_color,Point2i(),NULL,NULL,NULL,total_chars);
				total_chars+=main->lines[from_line].char_count;
				from_line++;
			}
		}
	}
}
示例#5
0
void ButtonArray::_notification(int p_what) {

    switch(p_what) {
    case NOTIFICATION_MOUSE_EXIT: {
        hover=-1;
        update();
    }
    break;
    case NOTIFICATION_READY: {
        MethodInfo mi;
        mi.name="mouse_sub_enter";

        add_user_signal(mi);

    }
    break;
    case NOTIFICATION_DRAW: {

        Size2 size=get_size();
        Size2 minsize=get_combined_minimum_size();
        Ref<StyleBox> style_normal = get_stylebox("normal");
        Ref<StyleBox> style_selected = get_stylebox("selected");
        Ref<StyleBox> style_focus = get_stylebox("focus");
        Ref<StyleBox> style_hover = get_stylebox("hover");
        Ref<Font> font_normal = get_font("font");
        Ref<Font> font_selected = get_font("font_selected");
        int icon_sep = get_constant("icon_separator");
        int button_sep = get_constant("button_separator");
        Color color_normal = get_color("font_color");
        Color color_selected = get_color("font_color_selected");

        int sep=button_sep;
        int ofs=0;
        int expand=0;

        switch(align) {
        case ALIGN_BEGIN: {

            ofs=0;
        }
        break;
        case ALIGN_CENTER: {

            ofs=Math::floor((size[orientation] - minsize[orientation])/2);
        }
        break;
        case ALIGN_END: {

            ofs=Math::floor((size[orientation] - minsize[orientation]));
        }
        break;
        case ALIGN_FILL: {

            if (buttons.size()>1)
                sep+=Math::floor((size[orientation]- minsize[orientation])/(buttons.size()-1.0));
            ofs=0;
        }
        break;
        case ALIGN_EXPAND_FILL: {

            ofs=0;
            expand=size[orientation] - minsize[orientation];
        }
        break;



        }

        int op_size = orientation==VERTICAL ? size.width : size.height;


        for(int i=0; i<buttons.size(); i++) {

            int ms = buttons[i]._ms_cache;
            int s=ms;
            if (expand>0) {
                s+=expand/buttons.size();
            }
            if(min_button_size != -1 && s < min_button_size) {
                s = min_button_size;
            }

            Rect2 r;
            r.pos[orientation]=ofs;
            r.pos[!orientation]=0;
            r.size[orientation]=s;
            r.size[!orientation]=op_size;

            Ref<Font> f;
            Color c;
            Point2 sbsize;
            Point2 sbofs;
            if (i==selected) {
                draw_style_box(style_selected,r);
                sbsize=style_selected->get_minimum_size();
                sbofs=style_selected->get_offset();
                f=font_selected;
                c=color_selected;
                if (has_focus())
                    draw_style_box(style_focus,r);
            } else {
                if (hover==i)
                    draw_style_box(style_hover,r);
                else if (!flat)
                    draw_style_box(style_normal,r);
                sbsize=style_normal->get_minimum_size();
                sbofs=style_normal->get_offset();
                f=font_normal;
                c=color_normal;
            }

            Size2 ssize = f->get_string_size(buttons[i].text);
            if (buttons[i].icon.is_valid()) {

                ssize.x+=buttons[i].icon->get_width();
            }
            Point2 text_ofs=((r.size-ssize-sbsize)/2.0+Point2(0,f->get_ascent())).floor()+sbofs;
            if (buttons[i].icon.is_valid()) {

                draw_texture(buttons[i].icon,r.pos+Point2(text_ofs.x,Math::floor((r.size.height-buttons[i].icon->get_height())/2.0)));
                text_ofs.x+=buttons[i].icon->get_width()+icon_sep;

            }
            draw_string(f,text_ofs+r.pos,buttons[i].text,c);
            buttons[i]._pos_cache=ofs;
            buttons[i]._size_cache=s;

            ofs+=s;
            ofs+=sep;
        }

    }
    break;
    }
}
示例#6
0
void GraphEdit::_notification(int p_what) {

	if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
		port_grab_distance_horizontal = get_constant("port_grab_distance_horizontal");
		port_grab_distance_vertical = get_constant("port_grab_distance_vertical");
	}
	if (p_what == NOTIFICATION_READY) {
		Size2 hmin = h_scroll->get_combined_minimum_size();
		Size2 vmin = v_scroll->get_combined_minimum_size();

		v_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -vmin.width);
		v_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
		v_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 0);
		v_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);

		h_scroll->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0);
		h_scroll->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
		h_scroll->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -hmin.height);
		h_scroll->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0);

		zoom_minus->set_icon(get_icon("minus"));
		zoom_reset->set_icon(get_icon("reset"));
		zoom_plus->set_icon(get_icon("more"));
		snap_button->set_icon(get_icon("snap"));
	}
	if (p_what == NOTIFICATION_DRAW) {

		draw_style_box(get_stylebox("bg"), Rect2(Point2(), get_size()));

		if (is_using_snap()) {
			//draw grid

			int snap = get_snap();

			Vector2 offset = get_scroll_ofs() / zoom;
			Size2 size = get_size() / zoom;

			Point2i from = (offset / float(snap)).floor();
			Point2i len = (size / float(snap)).floor() + Vector2(1, 1);

			Color grid_minor = get_color("grid_minor");
			Color grid_major = get_color("grid_major");

			for (int i = from.x; i < from.x + len.x; i++) {

				Color color;

				if (ABS(i) % 10 == 0)
					color = grid_major;
				else
					color = grid_minor;

				float base_ofs = i * snap * zoom - offset.x * zoom;
				draw_line(Vector2(base_ofs, 0), Vector2(base_ofs, get_size().height), color);
			}

			for (int i = from.y; i < from.y + len.y; i++) {

				Color color;

				if (ABS(i) % 10 == 0)
					color = grid_major;
				else
					color = grid_minor;

				float base_ofs = i * snap * zoom - offset.y * zoom;
				draw_line(Vector2(0, base_ofs), Vector2(get_size().width, base_ofs), color);
			}
		}
	}

	if (p_what == NOTIFICATION_RESIZED) {
		_update_scroll();
		top_layer->update();
	}
}
示例#7
0
void EditorAudioBus::_notification(int p_what) {

	if (p_what == NOTIFICATION_READY) {

		for (int i = 0; i < CHANNELS_MAX; i++) {
			channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
			channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
			channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
			channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
			channel[i].prev_active = true;
		}
		scale->set_texture(get_icon("BusVuDb", "EditorIcons"));

		disabled_vu = get_icon("BusVuFrozen", "EditorIcons");

		Color solo_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ffe337" : "#ffeb70");
		Color mute_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ff2929" : "#ff7070");
		Color bypass_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#22ccff" : "#70deff");

		solo->set_icon(get_icon("AudioBusSolo", "EditorIcons"));
		solo->add_color_override("icon_color_pressed", solo_color);
		mute->set_icon(get_icon("AudioBusMute", "EditorIcons"));
		mute->add_color_override("icon_color_pressed", mute_color);
		bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));
		bypass->add_color_override("icon_color_pressed", bypass_color);

		bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));

		update_bus();
		set_process(true);
	}

	if (p_what == NOTIFICATION_DRAW) {

		if (has_focus()) {
			draw_style_box(get_stylebox("focus", "Button"), Rect2(Vector2(), get_size()));
		} else if (is_master) {
			draw_style_box(get_stylebox("disabled", "Button"), Rect2(Vector2(), get_size()));
		}
	}

	if (p_what == NOTIFICATION_PROCESS) {

		if (cc != AudioServer::get_singleton()->get_bus_channels(get_index())) {
			cc = AudioServer::get_singleton()->get_bus_channels(get_index());
			_update_visible_channels();
		}

		for (int i = 0; i < cc; i++) {
			float real_peak[2] = { -100, -100 };
			bool activity_found = false;

			if (AudioServer::get_singleton()->is_bus_channel_active(get_index(), i)) {
				activity_found = true;
				real_peak[0] = MAX(real_peak[0], AudioServer::get_singleton()->get_bus_peak_volume_left_db(get_index(), i));
				real_peak[1] = MAX(real_peak[1], AudioServer::get_singleton()->get_bus_peak_volume_right_db(get_index(), i));
			}

			if (real_peak[0] > channel[i].peak_l) {
				channel[i].peak_l = real_peak[0];
			} else {
				channel[i].peak_l -= get_process_delta_time() * 60.0;
			}

			if (real_peak[1] > channel[i].peak_r) {
				channel[i].peak_r = real_peak[1];
			} else {
				channel[i].peak_r -= get_process_delta_time() * 60.0;
			}

			channel[i].vu_l->set_value(channel[i].peak_l);
			channel[i].vu_r->set_value(channel[i].peak_r);

			if (activity_found != channel[i].prev_active) {
				if (activity_found) {
					channel[i].vu_l->set_over_texture(Ref<Texture>());
					channel[i].vu_r->set_over_texture(Ref<Texture>());
				} else {
					channel[i].vu_l->set_over_texture(disabled_vu);
					channel[i].vu_r->set_over_texture(disabled_vu);
				}

				channel[i].prev_active = activity_found;
			}
		}
	}

	if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {

		for (int i = 0; i < CHANNELS_MAX; i++) {
			channel[i].peak_l = -100;
			channel[i].peak_r = -100;
			channel[i].prev_active = true;
		}

		set_process(is_visible_in_tree());
	}

	if (p_what == NOTIFICATION_THEME_CHANGED) {

		for (int i = 0; i < CHANNELS_MAX; i++) {
			channel[i].vu_l->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
			channel[i].vu_l->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
			channel[i].vu_r->set_under_texture(get_icon("BusVuEmpty", "EditorIcons"));
			channel[i].vu_r->set_progress_texture(get_icon("BusVuFull", "EditorIcons"));
			channel[i].prev_active = true;
		}
		scale->set_texture(get_icon("BusVuDb", "EditorIcons"));

		disabled_vu = get_icon("BusVuFrozen", "EditorIcons");

		solo->set_icon(get_icon("AudioBusSolo", "EditorIcons"));
		mute->set_icon(get_icon("AudioBusMute", "EditorIcons"));
		bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons"));

		bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
	}
}
示例#8
0
void EditorSpinSlider::_notification(int p_what) {

	if (p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT || p_what == MainLoop::NOTIFICATION_WM_FOCUS_OUT) {
		if (grabbing_spinner) {
			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
			grabbing_spinner = false;
			grabbing_spinner_attempt = false;
		}
	}

	if (p_what == NOTIFICATION_DRAW) {

		updown_offset = -1;

		Ref<StyleBox> sb = get_stylebox("normal", "LineEdit");
		draw_style_box(sb, Rect2(Vector2(), get_size()));
		Ref<Font> font = get_font("font", "LineEdit");

		int avail_width = get_size().width - sb->get_minimum_size().width - sb->get_minimum_size().width;
		avail_width -= font->get_string_size(label).width;
		Ref<Texture> updown = get_icon("updown", "SpinBox");

		if (get_step() == 1) {
			avail_width -= updown->get_width();
		}

		if (has_focus()) {
			Ref<StyleBox> focus = get_stylebox("focus", "LineEdit");
			draw_style_box(focus, Rect2(Vector2(), get_size()));
		}

		String numstr = get_text_value();

		int vofs = (get_size().height - font->get_height()) / 2 + font->get_ascent();

		Color fc = get_color("font_color", "LineEdit");

		int label_ofs = sb->get_offset().x + avail_width;
		draw_string(font, Vector2(label_ofs, vofs), label, fc * Color(1, 1, 1, 0.5));
		draw_string(font, Vector2(sb->get_offset().x, vofs), numstr, fc, avail_width);

		if (get_step() == 1) {
			Ref<Texture> updown = get_icon("updown", "SpinBox");
			int updown_vofs = (get_size().height - updown->get_height()) / 2;
			updown_offset = get_size().width - sb->get_margin(MARGIN_RIGHT) - updown->get_width();
			Color c(1, 1, 1);
			if (hover_updown) {
				c *= Color(1.2, 1.2, 1.2);
			}
			draw_texture(updown, Vector2(updown_offset, updown_vofs), c);
			if (grabber->is_visible()) {
				grabber->hide();
			}
		} else if (!hide_slider) {
			int grabber_w = 4 * EDSCALE;
			int width = get_size().width - sb->get_minimum_size().width - grabber_w;
			int ofs = sb->get_offset().x;
			int svofs = (get_size().height + vofs) / 2 - 1;
			Color c = fc;
			c.a = 0.2;

			draw_rect(Rect2(ofs, svofs + 1, width, 2 * EDSCALE), c);
			int gofs = get_as_ratio() * width;
			c.a = 0.9;
			Rect2 grabber_rect = Rect2(ofs + gofs, svofs + 1, grabber_w, 2 * EDSCALE);
			draw_rect(grabber_rect, c);

			bool display_grabber = (mouse_over_spin || mouse_over_grabber) && !grabbing_spinner;
			if (grabber->is_visible() != display_grabber) {
				if (display_grabber) {
					grabber->show();
				} else {
					grabber->hide();
				}
			}

			if (display_grabber) {
				Ref<Texture> grabber_tex;
				if (mouse_over_grabber) {
					grabber_tex = get_icon("grabber_highlight", "HSlider");
				} else {
					grabber_tex = get_icon("grabber", "HSlider");
				}

				if (grabber->get_texture() != grabber_tex) {
					grabber->set_texture(grabber_tex);
				}

				grabber->set_size(Size2(0, 0));
				grabber->set_position(get_global_position() + grabber_rect.position + grabber_rect.size * 0.5 - grabber->get_size() * 0.5);
				grabber_range = width;
			}
		}
	}

	if (p_what == NOTIFICATION_MOUSE_ENTER) {

		mouse_over_spin = true;
		update();
	}
	if (p_what == NOTIFICATION_MOUSE_EXIT) {

		mouse_over_spin = false;
		update();
	}
}
示例#9
0
void GraphNode::_notification(int p_what) {

	if (p_what==NOTIFICATION_DRAW) {

		Ref<StyleBox> sb;

		if (comment) {
			sb = get_stylebox( selected? "commentfocus" : "comment");

		} else {

			sb = get_stylebox( selected ? "selectedframe" : "frame");
		}

		sb=sb->duplicate();
		sb->call("set_modulate",modulate);
		Ref<Texture> port =get_icon("port");
		Ref<Texture> close =get_icon("close");
		Ref<Texture> resizer =get_icon("resizer");
		int close_offset = get_constant("close_offset");
		Ref<Font> title_font = get_font("title_font");
		int title_offset = get_constant("title_offset");
		Color title_color = get_color("title_color");
		Point2i icofs = -port->get_size()*0.5;
		int edgeofs=get_constant("port_offset");
		icofs.y+=sb->get_margin(MARGIN_TOP);



		draw_style_box(sb,Rect2(Point2(),get_size()));

		switch(overlay) {
			case OVERLAY_DISABLED: {

			} break;
			case OVERLAY_BREAKPOINT: {

				draw_style_box(get_stylebox("breakpoint"),Rect2(Point2(),get_size()));
			} break;
			case OVERLAY_POSITION: {
				draw_style_box(get_stylebox("position"),Rect2(Point2(),get_size()));

			} break;
		}

		int w = get_size().width-sb->get_minimum_size().x;

		if (show_close)
			w-=close->get_width();

		draw_string(title_font,Point2(sb->get_margin(MARGIN_LEFT),-title_font->get_height()+title_font->get_ascent()+title_offset),title,title_color,w);
		if (show_close) {
			Vector2 cpos = Point2(w+sb->get_margin(MARGIN_LEFT),-close->get_height()+close_offset);
			draw_texture(close,cpos);
			close_rect.pos=cpos;
			close_rect.size=close->get_size();
		} else {
			close_rect=Rect2();
		}

		for (Map<int,Slot>::Element *E=slot_info.front();E;E=E->next()) {

			if (E->key() < 0 || E->key()>=cache_y.size())
				continue;
			if (!slot_info.has(E->key()))
				continue;
			const Slot &s=slot_info[E->key()];
			//left
			if (s.enable_left) {
				Ref<Texture> p = port;
				if (s.custom_slot_left.is_valid()) {
					p=s.custom_slot_left;
				}
				p->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left);
			}
			if (s.enable_right) {
				Ref<Texture> p = port;
				if (s.custom_slot_right.is_valid()) {
					p=s.custom_slot_right;
				}
				p->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right);
			}

		}


		if (resizeable) {
			draw_texture(resizer,get_size()-resizer->get_size());
		}
	}

	if (p_what==NOTIFICATION_SORT_CHILDREN) {

		_resort();
	}

}
示例#10
0
void ItemList::_notification(int p_what) {

	if (p_what==NOTIFICATION_RESIZED) {
		shape_changed=true;
		update();
	}

	if (p_what==NOTIFICATION_DRAW) {

		VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
		Ref<StyleBox> bg = get_stylebox("bg");

		int mw = scroll_bar->get_minimum_size().x;
		scroll_bar->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,mw+bg->get_margin(MARGIN_RIGHT));
		scroll_bar->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,bg->get_margin(MARGIN_RIGHT));
		scroll_bar->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,bg->get_margin(MARGIN_TOP));
		scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,bg->get_margin(MARGIN_BOTTOM));


		Size2 size = get_size();

		float page = size.height-bg->get_minimum_size().height;
		int width = size.width - mw - bg->get_minimum_size().width;
		scroll_bar->set_page(page);

		draw_style_box(bg,Rect2(Point2(),size));

		int hseparation = get_constant("hseparation");
		int vseparation = get_constant("vseparation");
		int icon_margin = get_constant("icon_margin");
		int line_separation = get_constant("line_separation");

		Ref<StyleBox> sbsel = has_focus()?get_stylebox("selected_focus"):get_stylebox("selected");
		Ref<StyleBox> cursor = has_focus()?get_stylebox("cursor"):get_stylebox("cursor_unfocused");

		Ref<Font> font = get_font("font");
		Color guide_color = get_color("guide_color");
		Color font_color = get_color("font_color");
		Color font_color_selected = get_color("font_color_selected");
		int font_height = font->get_height();
		Vector<int> line_size_cache;
		Vector<int> line_limit_cache;

		if (max_text_lines) {
			line_size_cache.resize(max_text_lines);
			line_limit_cache.resize(max_text_lines);
		}

		if (has_focus()) {
			VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(),true);
			draw_style_box(get_stylebox("bg_focus"),Rect2(Point2(),size));
			VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(),false);
		}

		if (shape_changed) {

			//1- compute item minimum sizes
			for(int i=0;i<items.size();i++) {

				Size2 minsize;
				if (items[i].icon.is_valid()) {

					minsize=items[i].get_icon_size();

					if (min_icon_size.x!=0)
						minsize.x = MAX(minsize.x,min_icon_size.x);
					if (min_icon_size.y!=0)
						minsize.y = MAX(minsize.y,min_icon_size.y);

					if (items[i].text!="") {
						if (icon_mode==ICON_MODE_TOP) {
							minsize.y+=icon_margin;
						} else {
							minsize.x+=icon_margin;
						}
					}
				}

				if (items[i].text!="") {

					Size2 s = font->get_string_size(items[i].text);
					//s.width=MIN(s.width,fixed_column_width);



					if (icon_mode==ICON_MODE_TOP) {
						minsize.x=MAX(minsize.x,s.width);
						if (max_text_lines>0) {
							minsize.y+=(font_height+line_separation)*max_text_lines;
						} else {
							minsize.y+=s.height;
						}

					} else {
						minsize.y=MAX(minsize.y,s.height);
						minsize.x+=s.width;
					}
				}



				items[i].rect_cache.size=minsize;
				if (fixed_column_width>0)
					items[i].rect_cache.size.x=fixed_column_width;

			}

			int fit_size = size.x - bg->get_minimum_size().width - mw;

			//2-attempt best fit
			current_columns = 0x7FFFFFFF;
			if (max_columns>0)
				current_columns=max_columns;


			while(true) {
				//repeat util all fits
				//print_line("try with "+itos(current_columns));
				bool all_fit=true;
				Vector2 ofs;
				int col=0;
				int max_h=0;
				separators.clear();;
				for(int i=0;i<items.size();i++) {

					if (current_columns>1 && items[i].rect_cache.size.width+ofs.x > fit_size) {
						//went past
						current_columns=MAX(col,1);
						all_fit=false;
						break;
					}

					items[i].rect_cache.pos=ofs;
					max_h=MAX(max_h,items[i].rect_cache.size.y);
					ofs.x+=items[i].rect_cache.size.x;
					//print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x));
					if (col>0)
						ofs.x+=hseparation;
					col++;
					if (col==current_columns) {

						if (i<items.size()-1)
							separators.push_back(ofs.y+max_h+vseparation/2);
						ofs.x=0;
						ofs.y+=max_h+vseparation;
						col=0;
						max_h=0;
					}
				}

				if (all_fit) {
					float max = MAX(page,ofs.y+max_h);
					scroll_bar->set_max(max);
					//print_line("max: "+rtos(max)+" page "+rtos(page));
					if (max<=page) {
						scroll_bar->set_val(0);
						scroll_bar->hide();
					} else {
						scroll_bar->show();
					}
					break;
				}
			}


			shape_changed=false;
		}



		Vector2 base_ofs = bg->get_offset();
		base_ofs.y-=int(scroll_bar->get_val());

		Rect2 clip(Point2(),size-bg->get_minimum_size()+Vector2(0,scroll_bar->get_val()));

		for(int i=0;i<items.size();i++) {


			Rect2 rcache = items[i].rect_cache;

			if (!clip.intersects(rcache))
				continue;


			if (current_columns==1) {
				rcache.size.width = width-rcache.pos.x;
			}

			Rect2 r=rcache;
			r.pos+=base_ofs;

			// Use stylebox to dimension potential bg color, even if not selected
			r.pos.x-=sbsel->get_margin(MARGIN_LEFT);
			r.size.x+=sbsel->get_margin(MARGIN_LEFT)+sbsel->get_margin(MARGIN_RIGHT);
			r.pos.y-=sbsel->get_margin(MARGIN_TOP);
			r.size.y+=sbsel->get_margin(MARGIN_TOP)+sbsel->get_margin(MARGIN_BOTTOM);

			if (items[i].selected) {
				draw_style_box(sbsel,r);
			}
			if (items[i].custom_bg.a>0.001) {
				r.pos.x+=2;
				r.size.x-=4;
				r.pos.y+=2;
				r.size.y-=4;
				draw_rect(r,items[i].custom_bg);
			}


			Vector2 text_ofs;
			if (items[i].icon.is_valid()) {

				Size2 icon_size = items[i].get_icon_size();

				Vector2 icon_ofs;
				if (min_icon_size!=Vector2()) {
					icon_ofs = (min_icon_size - icon_size)/2;
				}

				Point2 pos = items[i].rect_cache.pos + icon_ofs + base_ofs;

				if (icon_mode==ICON_MODE_TOP) {

					pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width)/2);
					text_ofs.y = MAX(icon_size.height, min_icon_size.y) + icon_margin;
				} else {

					pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height)/2);
					text_ofs.x = MAX(icon_size.width, min_icon_size.x) + icon_margin;
				}

				if (items[i].icon_region.has_no_area())
					draw_texture(items[i].icon, pos);
				else
					draw_texture_rect_region(items[i].icon, Rect2(pos, icon_size), items[i].icon_region);

			}

			if (items[i].tag_icon.is_valid()) {

				draw_texture(items[i].tag_icon,items[i].rect_cache.pos+base_ofs);
			}

			if (items[i].text!="") {

				int max_len=-1;

				Vector2 size = font->get_string_size(items[i].text);
				if (fixed_column_width)
					max_len=fixed_column_width;
				else
					max_len=size.x;

				if (icon_mode==ICON_MODE_TOP && max_text_lines>0) {

					int ss = items[i].text.length();
					float ofs=0;
					int line=0;
					for(int j=0;j<=ss;j++) {

						int cs = j<ss?font->get_char_size(items[i].text[j],items[i].text[j+1]).x:0;
						if (ofs+cs>max_len || j==ss) {
							line_limit_cache[line]=j;
							line_size_cache[line]=ofs;
							line++;
							ofs=0;
							if (line>=max_text_lines)
								break;
						} else {
							ofs+=cs;
						}

					}

					line=0;
					ofs=0;

					text_ofs.y+=font->get_ascent();
					text_ofs=text_ofs.floor();
					text_ofs+=base_ofs;
					text_ofs+=items[i].rect_cache.pos;

					for(int j=0;j<ss;j++) {

						if (j==line_limit_cache[line]) {
							line++;
							ofs=0;
							if (line>=max_text_lines)
								break;
						}
						ofs+=font->draw_char(get_canvas_item(),text_ofs+Vector2(ofs+(max_len-line_size_cache[line])/2,line*(font_height+line_separation)).floor(),items[i].text[j],items[i].text[j+1],items[i].selected?font_color_selected:font_color);
					}

					//special multiline mode
				} else {

					if (fixed_column_width>0)
						size.x=MIN(size.x,fixed_column_width);

					if (icon_mode==ICON_MODE_TOP) {
						text_ofs.x+=(items[i].rect_cache.size.width-size.x)/2;
					} else {
						text_ofs.y+=(items[i].rect_cache.size.height-size.y)/2;
					}

					text_ofs.y+=font->get_ascent();
					text_ofs=text_ofs.floor();
					text_ofs+=base_ofs;
					text_ofs+=items[i].rect_cache.pos;

					draw_string(font,text_ofs,items[i].text,items[i].selected?font_color_selected:font_color,max_len+1);
				}


			}

			if (select_mode==SELECT_MULTI && i==current) {

				Rect2 r=rcache;
				r.pos+=base_ofs;
				draw_style_box(cursor,r);

			}
		}

		for(int i=0;i<separators.size();i++) {
			draw_line(Vector2(bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),Vector2(size.width-bg->get_margin(MARGIN_LEFT),base_ofs.y+separators[i]),guide_color);
		}


		if (ensure_selected_visible && current>=0 && current <=items.size()) {

			Rect2 r = items[current].rect_cache;
			int from = scroll_bar->get_val();
			int to = from + scroll_bar->get_page();

			if (r.pos.y < from) {
				scroll_bar->set_val(r.pos.y);
			} else if (r.pos.y+r.size.y > to) {
				scroll_bar->set_val(r.pos.y+r.size.y - (to-from));
			}


		}

		ensure_selected_visible=false;

	}
}
示例#11
0
void EditorPath::_notification(int p_what) {


	switch(p_what) {

		case NOTIFICATION_MOUSE_ENTER: {
			mouse_over=true;
			update();
		} break;
		case NOTIFICATION_MOUSE_EXIT: {
			mouse_over=false;
			update();
		} break;
		case NOTIFICATION_DRAW: {

			RID ci=get_canvas_item();
			Ref<Font> label_font = get_font("font","Label");
			Size2i size = get_size();
			Ref<Texture> sn = get_icon("SmallNext","EditorIcons");
			Ref<StyleBox> sb = get_stylebox("pressed","Button");


			int ofs=sb->get_margin(MARGIN_LEFT);

			if (mouse_over) {
				draw_style_box(sb,Rect2(Point2(),get_size()));
			}

			for(int i=0;i<history->get_path_size();i++) {

				Object *obj = ObjectDB::get_instance(history->get_path_object(i));
				if (!obj)
					continue;

				String type = obj->get_class();

				Ref<Texture> icon;

				if (has_icon(obj->get_class(),"EditorIcons"))
					icon=get_icon(obj->get_class(),"EditorIcons");
				else
					icon=get_icon("Object","EditorIcons");


				icon->draw(ci,Point2i(ofs,(size.height-icon->get_height())/2));

				ofs+=icon->get_width();

				if (i==history->get_path_size()-1) {
					//add name
					ofs+=4;
					int left = size.width - ofs;
					if (left<0)
						continue;
					String name;
					if (obj->cast_to<Resource>()) {

						Resource *r = obj->cast_to<Resource>();
						if (r->get_path().is_resource_file())
							name=r->get_path().get_file();
						else
							name=r->get_name();

						if (name=="")
							name=r->get_class();
					} else if (obj->cast_to<Node>()) {

						name=obj->cast_to<Node>()->get_name();
					} else if (obj->cast_to<Resource>() && obj->cast_to<Resource>()->get_name()!="") {
						name=obj->cast_to<Resource>()->get_name();
					} else {
						name=obj->get_class();
					}

					set_tooltip(obj->get_class());


					label_font->draw(ci,Point2i(ofs,(size.height-label_font->get_height())/2+label_font->get_ascent()),name,Color(1,1,1),left);
				} else {
					//add arrow

					//sn->draw(ci,Point2i(ofs,(size.height-sn->get_height())/2));
					//ofs+=sn->get_width();
					ofs+=5; //just looks better! somehow

				}
			}

		} break;
	}
}
示例#12
0
void CurveEditor::_draw() {
	if (_curve_ref.is_null())
		return;
	Curve &curve = **_curve_ref;

	update_view_transform();

	// Background

	Vector2 view_size = get_rect().size;
	draw_style_box(get_stylebox("bg", "Tree"), Rect2(Point2(), view_size));

	// Grid

	draw_set_transform_matrix(_world_to_view);

	Vector2 min_edge = get_world_pos(Vector2(0, view_size.y));
	Vector2 max_edge = get_world_pos(Vector2(view_size.x, 0));

	const Color grid_color0 = get_color("grid_major_color", "Editor");
	const Color grid_color1 = get_color("grid_minor_color", "Editor");
	draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0);
	draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0);
	draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0);
	draw_line(Vector2(1, max_edge.y), Vector2(1, min_edge.y), grid_color0);

	float curve_height = (curve.get_max_value() - curve.get_min_value());
	const Vector2 grid_step(0.25, 0.5 * curve_height);

	for (real_t x = 0; x < 1.0; x += grid_step.x) {
		draw_line(Vector2(x, min_edge.y), Vector2(x, max_edge.y), grid_color1);
	}
	for (real_t y = curve.get_min_value(); y < curve.get_max_value(); y += grid_step.y) {
		draw_line(Vector2(min_edge.x, y), Vector2(max_edge.x, y), grid_color1);
	}

	// Markings

	draw_set_transform_matrix(Transform2D());

	Ref<Font> font = get_font("font", "Label");
	float font_height = font->get_height();
	Color text_color = get_color("font_color", "Editor");

	{
		// X axis
		float y = curve.get_min_value();
		Vector2 off(0, font_height - 1);
		draw_string(font, get_view_pos(Vector2(0, y)) + off, "0.0", text_color);
		draw_string(font, get_view_pos(Vector2(0.25, y)) + off, "0.25", text_color);
		draw_string(font, get_view_pos(Vector2(0.5, y)) + off, "0.5", text_color);
		draw_string(font, get_view_pos(Vector2(0.75, y)) + off, "0.75", text_color);
		draw_string(font, get_view_pos(Vector2(1, y)) + off, "1.0", text_color);
	}

	{
		// Y axis
		float m0 = curve.get_min_value();
		float m1 = 0.5 * (curve.get_min_value() + curve.get_max_value());
		float m2 = curve.get_max_value();
		Vector2 off(1, -1);
		draw_string(font, get_view_pos(Vector2(0, m0)) + off, String::num(m0, 2), text_color);
		draw_string(font, get_view_pos(Vector2(0, m1)) + off, String::num(m1, 2), text_color);
		draw_string(font, get_view_pos(Vector2(0, m2)) + off, String::num(m2, 3), text_color);
	}

	// Draw tangents for current point

	if (_selected_point >= 0) {

		const Color tangent_color = get_color("accent_color", "Editor");

		int i = _selected_point;
		Vector2 pos = curve.get_point_position(i);

		if (i != 0) {
			Vector2 control_pos = get_tangent_view_pos(i, TANGENT_LEFT);
			draw_line(get_view_pos(pos), control_pos, tangent_color);
			draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color);
		}

		if (i != curve.get_point_count() - 1) {
			Vector2 control_pos = get_tangent_view_pos(i, TANGENT_RIGHT);
			draw_line(get_view_pos(pos), control_pos, tangent_color);
			draw_rect(Rect2(control_pos, Vector2(1, 1)).grow(2), tangent_color);
		}
	}

	// Draw lines

	draw_set_transform_matrix(_world_to_view);

	const Color line_color = get_color("highlight_color", "Editor");
	const Color edge_line_color = get_color("font_color", "Editor");

	CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color);
	plot_curve_accurate(curve, 4.f / view_size.x, plot_func);

	// Draw points

	draw_set_transform_matrix(Transform2D());

	const Color point_color = get_color("font_color", "Editor");
	const Color selected_point_color = get_color("accent_color", "Editor");

	for (int i = 0; i < curve.get_point_count(); ++i) {
		Vector2 pos = curve.get_point_position(i);
		draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(3), i == _selected_point ? selected_point_color : point_color);
		// TODO Circles are prettier. Needs a fix! Or a texture
		//draw_circle(pos, 2, point_color);
	}

	// Hover

	if (_hover_point != -1) {
		const Color hover_color = line_color;
		Vector2 pos = curve.get_point_position(_hover_point);
		stroke_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color);
	}

	// Help text

	if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) {
		text_color.a *= 0.4;
		draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color);
	}
}
示例#13
0
void ItemList::_notification(int p_what) {

	if (p_what == NOTIFICATION_RESIZED) {
		shape_changed = true;
		update();
	}

	if (p_what == NOTIFICATION_DRAW) {

		Ref<StyleBox> bg = get_stylebox("bg");

		int mw = scroll_bar->get_minimum_size().x;
		scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw);
		scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
		scroll_bar->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, bg->get_margin(MARGIN_TOP));
		scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -bg->get_margin(MARGIN_BOTTOM));

		Size2 size = get_size();

		int width = size.width - bg->get_minimum_size().width;
		if (scroll_bar->is_visible()) {
			width -= mw + bg->get_margin(MARGIN_RIGHT);
		}

		draw_style_box(bg, Rect2(Point2(), size));

		int hseparation = get_constant("hseparation");
		int vseparation = get_constant("vseparation");
		int icon_margin = get_constant("icon_margin");
		int line_separation = get_constant("line_separation");

		Ref<StyleBox> sbsel = has_focus() ? get_stylebox("selected_focus") : get_stylebox("selected");
		Ref<StyleBox> cursor = has_focus() ? get_stylebox("cursor") : get_stylebox("cursor_unfocused");

		Ref<Font> font = get_font("font");
		Color guide_color = get_color("guide_color");
		Color font_color = get_color("font_color");
		Color font_color_selected = get_color("font_color_selected");
		int font_height = font->get_height();
		Vector<int> line_size_cache;
		Vector<int> line_limit_cache;

		if (max_text_lines) {
			line_size_cache.resize(max_text_lines);
			line_limit_cache.resize(max_text_lines);
		}

		if (has_focus()) {
			draw_style_box(get_stylebox("bg_focus"), Rect2(Point2(), size));
		}

		if (shape_changed) {

			float max_column_width = 0;

			//1- compute item minimum sizes
			for (int i = 0; i < items.size(); i++) {

				Size2 minsize;
				if (items[i].icon.is_valid()) {

					if (fixed_icon_size.x > 0 && fixed_icon_size.y > 0) {
						minsize = fixed_icon_size * icon_scale;
					} else {
						minsize = items[i].get_icon_size() * icon_scale;
					}

					if (items[i].text != "") {
						if (icon_mode == ICON_MODE_TOP) {
							minsize.y += icon_margin;
						} else {
							minsize.x += icon_margin;
						}
					}
				}

				if (items[i].text != "") {

					Size2 s = font->get_string_size(items[i].text);
					//s.width=MIN(s.width,fixed_column_width);

					if (icon_mode == ICON_MODE_TOP) {
						minsize.x = MAX(minsize.x, s.width);
						if (max_text_lines > 0) {
							minsize.y += (font_height + line_separation) * max_text_lines;
						} else {
							minsize.y += s.height;
						}

					} else {
						minsize.y = MAX(minsize.y, s.height);
						minsize.x += s.width;
					}
				}

				if (fixed_column_width > 0)
					minsize.x = fixed_column_width;
				max_column_width = MAX(max_column_width, minsize.x);

				// elements need to adapt to the selected size
				minsize.y += vseparation;
				minsize.x += hseparation;
				items[i].rect_cache.size = minsize;
				items[i].min_rect_cache.size = minsize;
			}

			int fit_size = size.x - bg->get_minimum_size().width - mw;

			//2-attempt best fit
			current_columns = 0x7FFFFFFF;
			if (max_columns > 0)
				current_columns = max_columns;

			while (true) {
				//repeat util all fits
				bool all_fit = true;
				Vector2 ofs;
				int col = 0;
				int max_h = 0;
				separators.clear();
				for (int i = 0; i < items.size(); i++) {

					if (current_columns > 1 && items[i].rect_cache.size.width + ofs.x > fit_size) {
						//went past
						current_columns = MAX(col, 1);
						all_fit = false;
						break;
					}

					if (same_column_width)
						items[i].rect_cache.size.x = max_column_width;
					items[i].rect_cache.position = ofs;
					max_h = MAX(max_h, items[i].rect_cache.size.y);
					ofs.x += items[i].rect_cache.size.x + hseparation;
					col++;
					if (col == current_columns) {

						if (i < items.size() - 1)
							separators.push_back(ofs.y + max_h + vseparation / 2);

						for (int j = i; j >= 0 && col > 0; j--, col--) {
							items[j].rect_cache.size.y = max_h;
						}

						ofs.x = 0;
						ofs.y += max_h + vseparation;
						col = 0;
						max_h = 0;
					}
				}

				for (int j = items.size() - 1; j >= 0 && col > 0; j--, col--) {
					items[j].rect_cache.size.y = max_h;
				}

				if (all_fit) {
					float page = size.height - bg->get_minimum_size().height;
					float max = MAX(page, ofs.y + max_h);
					if (auto_height)
						auto_height_value = ofs.y + max_h + bg->get_minimum_size().height;
					scroll_bar->set_max(max);
					scroll_bar->set_page(page);
					if (max <= page) {
						scroll_bar->set_value(0);
						scroll_bar->hide();
					} else {
						scroll_bar->show();
					}
					break;
				}
			}

			shape_changed = false;
		}

		//ensure_selected_visible needs to be checked before we draw the list.
		if (ensure_selected_visible && current >= 0 && current <= items.size()) {

			Rect2 r = items[current].rect_cache;
			int from = scroll_bar->get_value();
			int to = from + scroll_bar->get_page();

			if (r.position.y < from) {
				scroll_bar->set_value(r.position.y);
			} else if (r.position.y + r.size.y > to) {
				scroll_bar->set_value(r.position.y + r.size.y - (to - from));
			}
		}

		ensure_selected_visible = false;

		Vector2 base_ofs = bg->get_offset();
		base_ofs.y -= int(scroll_bar->get_value());

		Rect2 clip(Point2(), size - bg->get_minimum_size() + Vector2(0, scroll_bar->get_value()));

		for (int i = 0; i < items.size(); i++) {

			Rect2 rcache = items[i].rect_cache;

			if (!clip.intersects(rcache))
				continue;

			if (current_columns == 1) {
				rcache.size.width = width - rcache.position.x;
			}

			if (items[i].selected) {
				Rect2 r = rcache;
				r.position += base_ofs;
				r.position.y -= vseparation / 2;
				r.size.y += vseparation;
				r.position.x -= hseparation / 2;
				r.size.x += hseparation;

				draw_style_box(sbsel, r);
			}
			if (items[i].custom_bg.a > 0.001) {
				Rect2 r = rcache;
				r.position += base_ofs;

				// Size rect to make the align the temperature colors
				r.position.y -= vseparation / 2;
				r.size.y += vseparation;
				r.position.x -= hseparation / 2;
				r.size.x += hseparation;

				draw_rect(r, items[i].custom_bg);
			}

			Vector2 text_ofs;
			if (items[i].icon.is_valid()) {

				Size2 icon_size;
				//= _adjust_to_max_size(items[i].get_icon_size(),fixed_icon_size) * icon_scale;

				if (fixed_icon_size.x > 0 && fixed_icon_size.y > 0) {
					icon_size = fixed_icon_size * icon_scale;
				} else {
					icon_size = items[i].get_icon_size() * icon_scale;
				}

				Vector2 icon_ofs;

				Point2 pos = items[i].rect_cache.position + icon_ofs + base_ofs;

				if (icon_mode == ICON_MODE_TOP) {

					pos.x += Math::floor((items[i].rect_cache.size.width - icon_size.width) / 2);
					pos.y += MIN(
							Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2),
							items[i].rect_cache.size.height - items[i].min_rect_cache.size.height);
					text_ofs.y = icon_size.height + icon_margin;
					text_ofs.y += items[i].rect_cache.size.height - items[i].min_rect_cache.size.height;
				} else {

					pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height) / 2);
					text_ofs.x = icon_size.width + icon_margin;
				}

				Rect2 draw_rect = Rect2(pos, icon_size);

				if (fixed_icon_size.x > 0 && fixed_icon_size.y > 0) {
					Rect2 adj = _adjust_to_max_size(items[i].get_icon_size() * icon_scale, icon_size);
					draw_rect.position += adj.position;
					draw_rect.size = adj.size;
				}

				Color modulate = Color(1, 1, 1, 1);
				if (items[i].disabled)
					modulate.a *= 0.5;

				if (items[i].icon_region.has_no_area())
					draw_texture_rect(items[i].icon, draw_rect, false, modulate);
				else
					draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region, modulate);
			}

			if (items[i].tag_icon.is_valid()) {

				draw_texture(items[i].tag_icon, items[i].rect_cache.position + base_ofs);
			}

			if (items[i].text != "") {

				int max_len = -1;

				Vector2 size = font->get_string_size(items[i].text);
				if (fixed_column_width)
					max_len = fixed_column_width;
				else if (same_column_width)
					max_len = items[i].rect_cache.size.x;
				else
					max_len = size.x;

				Color modulate = items[i].selected ? font_color_selected : (items[i].custom_fg != Color() ? items[i].custom_fg : font_color);
				if (items[i].disabled)
					modulate.a *= 0.5;

				if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {

					int ss = items[i].text.length();
					float ofs = 0;
					int line = 0;
					for (int j = 0; j <= ss; j++) {

						int cs = j < ss ? font->get_char_size(items[i].text[j], items[i].text[j + 1]).x : 0;
						if (ofs + cs > max_len || j == ss) {
							line_limit_cache[line] = j;
							line_size_cache[line] = ofs;
							line++;
							ofs = 0;
							if (line >= max_text_lines)
								break;
						} else {
							ofs += cs;
						}
					}

					line = 0;
					ofs = 0;

					text_ofs.y += font->get_ascent();
					text_ofs = text_ofs.floor();
					text_ofs += base_ofs;
					text_ofs += items[i].rect_cache.position;

					for (int j = 0; j < ss; j++) {

						if (j == line_limit_cache[line]) {
							line++;
							ofs = 0;
							if (line >= max_text_lines)
								break;
						}
						ofs += font->draw_char(get_canvas_item(), text_ofs + Vector2(ofs + (max_len - line_size_cache[line]) / 2, line * (font_height + line_separation)).floor(), items[i].text[j], items[i].text[j + 1], modulate);
					}

					//special multiline mode
				} else {

					if (fixed_column_width > 0)
						size.x = MIN(size.x, fixed_column_width);

					if (icon_mode == ICON_MODE_TOP) {
						text_ofs.x += (items[i].rect_cache.size.width - size.x) / 2;
					} else {
						text_ofs.y += (items[i].rect_cache.size.height - size.y) / 2;
					}

					text_ofs.y += font->get_ascent();
					text_ofs = text_ofs.floor();
					text_ofs += base_ofs;
					text_ofs += items[i].rect_cache.position;

					draw_string(font, text_ofs, items[i].text, modulate, max_len + 1);
				}
			}

			if (select_mode == SELECT_MULTI && i == current) {

				Rect2 r = rcache;
				r.position += base_ofs;
				r.position.y -= vseparation / 2;
				r.size.y += vseparation;
				r.position.x -= hseparation / 2;
				r.size.x += hseparation;
				draw_style_box(cursor, r);
			}
		}

		for (int i = 0; i < separators.size(); i++) {
			draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_RIGHT), base_ofs.y + separators[i]), guide_color);
		}
	}
}