Path: blob/master/scene/gui/aspect_ratio_container.cpp
9902 views
/**************************************************************************/1/* aspect_ratio_container.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "aspect_ratio_container.h"3132#include "scene/gui/texture_rect.h"3334Size2 AspectRatioContainer::get_minimum_size() const {35Size2 ms;36for (int i = 0; i < get_child_count(); i++) {37Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);38if (!c) {39continue;40}41Size2 minsize = c->get_combined_minimum_size();42ms = ms.max(minsize);43}44return ms;45}4647void AspectRatioContainer::set_ratio(float p_ratio) {48if (ratio == p_ratio) {49return;50}51ratio = p_ratio;52queue_sort();53}5455void AspectRatioContainer::set_stretch_mode(StretchMode p_mode) {56if (stretch_mode == p_mode) {57return;58}59stretch_mode = p_mode;60queue_sort();61}6263void AspectRatioContainer::set_alignment_horizontal(AlignmentMode p_alignment_horizontal) {64if (alignment_horizontal == p_alignment_horizontal) {65return;66}67alignment_horizontal = p_alignment_horizontal;68queue_sort();69}7071void AspectRatioContainer::set_alignment_vertical(AlignmentMode p_alignment_vertical) {72if (alignment_vertical == p_alignment_vertical) {73return;74}75alignment_vertical = p_alignment_vertical;76queue_sort();77}7879Vector<int> AspectRatioContainer::get_allowed_size_flags_horizontal() const {80Vector<int> flags;81flags.append(SIZE_FILL);82flags.append(SIZE_SHRINK_BEGIN);83flags.append(SIZE_SHRINK_CENTER);84flags.append(SIZE_SHRINK_END);85return flags;86}8788Vector<int> AspectRatioContainer::get_allowed_size_flags_vertical() const {89Vector<int> flags;90flags.append(SIZE_FILL);91flags.append(SIZE_SHRINK_BEGIN);92flags.append(SIZE_SHRINK_CENTER);93flags.append(SIZE_SHRINK_END);94return flags;95}9697void AspectRatioContainer::_notification(int p_what) {98switch (p_what) {99case NOTIFICATION_SORT_CHILDREN: {100bool rtl = is_layout_rtl();101Size2 size = get_size();102for (int i = 0; i < get_child_count(); i++) {103Control *c = as_sortable_control(get_child(i));104if (!c) {105continue;106}107108// Temporary fix for editor crash.109TextureRect *trect = Object::cast_to<TextureRect>(c);110if (trect) {111if (trect->get_expand_mode() == TextureRect::EXPAND_FIT_WIDTH_PROPORTIONAL || trect->get_expand_mode() == TextureRect::EXPAND_FIT_HEIGHT_PROPORTIONAL) {112WARN_PRINT_ONCE("Proportional TextureRect is currently not supported inside AspectRatioContainer");113continue;114}115}116117Size2 child_minsize = c->get_combined_minimum_size();118Size2 child_size = Size2(ratio, 1.0);119float scale_factor = 1.0;120121switch (stretch_mode) {122case STRETCH_WIDTH_CONTROLS_HEIGHT: {123scale_factor = size.x / child_size.x;124} break;125case STRETCH_HEIGHT_CONTROLS_WIDTH: {126scale_factor = size.y / child_size.y;127} break;128case STRETCH_FIT: {129scale_factor = MIN(size.x / child_size.x, size.y / child_size.y);130} break;131case STRETCH_COVER: {132scale_factor = MAX(size.x / child_size.x, size.y / child_size.y);133} break;134}135child_size *= scale_factor;136child_size = child_size.max(child_minsize);137138float align_x = 0.5;139switch (alignment_horizontal) {140case ALIGNMENT_BEGIN: {141align_x = 0.0;142} break;143case ALIGNMENT_CENTER: {144align_x = 0.5;145} break;146case ALIGNMENT_END: {147align_x = 1.0;148} break;149}150float align_y = 0.5;151switch (alignment_vertical) {152case ALIGNMENT_BEGIN: {153align_y = 0.0;154} break;155case ALIGNMENT_CENTER: {156align_y = 0.5;157} break;158case ALIGNMENT_END: {159align_y = 1.0;160} break;161}162Vector2 offset = (size - child_size) * Vector2(align_x, align_y);163164if (rtl) {165fit_child_in_rect(c, Rect2(Vector2(size.x - offset.x - child_size.x, offset.y), child_size));166} else {167fit_child_in_rect(c, Rect2(offset, child_size));168}169}170} break;171}172}173174void AspectRatioContainer::_bind_methods() {175ClassDB::bind_method(D_METHOD("set_ratio", "ratio"), &AspectRatioContainer::set_ratio);176ClassDB::bind_method(D_METHOD("get_ratio"), &AspectRatioContainer::get_ratio);177178ClassDB::bind_method(D_METHOD("set_stretch_mode", "stretch_mode"), &AspectRatioContainer::set_stretch_mode);179ClassDB::bind_method(D_METHOD("get_stretch_mode"), &AspectRatioContainer::get_stretch_mode);180181ClassDB::bind_method(D_METHOD("set_alignment_horizontal", "alignment_horizontal"), &AspectRatioContainer::set_alignment_horizontal);182ClassDB::bind_method(D_METHOD("get_alignment_horizontal"), &AspectRatioContainer::get_alignment_horizontal);183184ClassDB::bind_method(D_METHOD("set_alignment_vertical", "alignment_vertical"), &AspectRatioContainer::set_alignment_vertical);185ClassDB::bind_method(D_METHOD("get_alignment_vertical"), &AspectRatioContainer::get_alignment_vertical);186187ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio", PROPERTY_HINT_RANGE, "0.001,10.0,0.0001,or_greater"), "set_ratio", "get_ratio");188ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width Controls Height,Height Controls Width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");189190ADD_GROUP("Alignment", "alignment_");191ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment_horizontal", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment_horizontal", "get_alignment_horizontal");192ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment_vertical", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment_vertical", "get_alignment_vertical");193194BIND_ENUM_CONSTANT(STRETCH_WIDTH_CONTROLS_HEIGHT);195BIND_ENUM_CONSTANT(STRETCH_HEIGHT_CONTROLS_WIDTH);196BIND_ENUM_CONSTANT(STRETCH_FIT);197BIND_ENUM_CONSTANT(STRETCH_COVER);198199BIND_ENUM_CONSTANT(ALIGNMENT_BEGIN);200BIND_ENUM_CONSTANT(ALIGNMENT_CENTER);201BIND_ENUM_CONSTANT(ALIGNMENT_END);202}203204205