diff options
24 files changed, 637 insertions, 69 deletions
diff --git a/core/image.cpp b/core/image.cpp index 023a058667..76f21a25de 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -423,7 +423,7 @@ void Image::convert(Format p_new_format) { for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - new_img.put_pixel(i, j, get_pixel(i, j)); + new_img.set_pixel(i, j, get_pixel(i, j)); } } @@ -1737,7 +1737,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); - put_pixel(dst_x, dst_y, dc); + set_pixel(dst_x, dst_y, dc); } } @@ -1792,7 +1792,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); - put_pixel(dst_x, dst_y, dc); + set_pixel(dst_x, dst_y, dc); } } } @@ -1812,7 +1812,7 @@ void Image::fill(const Color &c) { int pixel_size = get_format_pixel_size(format); // put first pixel with the format-aware API - put_pixel(0, 0, c); + set_pixel(0, 0, c); for (int y = 0; y < height; y++) { @@ -2041,12 +2041,12 @@ Color Image::get_pixel(int p_x, int p_y) const { return Color(); } -void Image::put_pixel(int p_x, int p_y, const Color &p_color) { +void Image::set_pixel(int p_x, int p_y, const Color &p_color) { uint8_t *ptr = write_lock.ptr(); #ifdef DEBUG_ENABLED if (!ptr) { - ERR_EXPLAIN("Image must be locked with 'lock()' before using put_pixel()"); + ERR_EXPLAIN("Image must be locked with 'lock()' before using set_pixel()"); ERR_FAIL_COND(!ptr); } @@ -2160,7 +2160,7 @@ void Image::put_pixel(int p_x, int p_y, const Color &p_color) { } break; default: { - ERR_EXPLAIN("Can't put_pixel() on compressed image, sorry."); + ERR_EXPLAIN("Can't set_pixel() on compressed image, sorry."); ERR_FAIL(); } } @@ -2270,7 +2270,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("lock"), &Image::lock); ClassDB::bind_method(D_METHOD("unlock"), &Image::unlock); - ClassDB::bind_method(D_METHOD("put_pixel", "x", "y", "color"), &Image::put_pixel); + ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel); ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); diff --git a/core/image.h b/core/image.h index e523f703fa..7acc4744e9 100644 --- a/core/image.h +++ b/core/image.h @@ -315,7 +315,7 @@ public: DetectChannels get_detected_channels(); Color get_pixel(int p_x, int p_y) const; - void put_pixel(int p_x, int p_y, const Color &p_color); + void set_pixel(int p_x, int p_y, const Color &p_color); void copy_internals_from(const Ref<Image> &p_image) { ERR_FAIL_COND(p_image.is_null()); diff --git a/doc/base/classes.xml b/doc/base/classes.xml index af90b5cde0..6ff3e0fa29 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -388,7 +388,8 @@ <argument index="0" name="json" type="String"> </argument> <description> - Parse json text to a Variant (use [method typeof] to check if it is what you expect). + Parse JSON text to a Variant (use [method typeof] to check if it is what you expect). + Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert every numerical values to [float] types. </description> </method> <method name="pow"> @@ -19217,7 +19218,7 @@ <description> </description> </method> - <method name="put_pixel"> + <method name="set_pixel"> <argument index="0" name="x" type="int"> </argument> <argument index="1" name="y" type="int"> diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index cb42970921..3f060cb97f 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -16,6 +16,7 @@ attribute vec2 uv_in; // attrib:4 #endif attribute vec2 uv2_in; // attrib:5 + #ifdef USE_CUBEMAP varying vec3 cube_interp; #else @@ -58,7 +59,9 @@ float sRGB_gamma_correct(float c){ #define LUM_RANGE 4.0 -#ifdef USE_CUBEMAP +#ifdef USE_ARRAY +uniform sampler2DArray source; +#elif defined(USE_CUBEMAP) varying vec3 cube_interp; uniform samplerCube source_cube; #else @@ -145,23 +148,17 @@ uniform float custom_alpha; void main() { //vec4 color = color_interp; -#ifdef USE_HIGHP_SOURCE -#ifdef USE_CUBEMAP + +#ifdef USE_ARRAY + highp vec4 color = textureLod( source, vec3(uv_interp,0.0),0.0 ); +#elif defined(USE_CUBEMAP) highp vec4 color = textureCube( source_cube, normalize(cube_interp) ); #else highp vec4 color = texture2D( source, uv_interp ); #endif -#else - -#ifdef USE_CUBEMAP - vec4 color = textureCube( source_cube, normalize(cube_interp) ); - -#else - vec4 color = texture2D( source, uv_interp ); -#endif #endif diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 08ff51866d..3b3ce73264 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1889,6 +1889,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ } else { glBindTexture(GL_TEXTURE_2D, p_base_env); } + state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP, true); state.scene_shader.set_conditional(SceneShaderGLES3::USE_RADIANCE_MAP_ARRAY, storage->config.use_texture_array_environment); } else { @@ -3980,7 +3981,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const } else { - use_mrt = env && (state.used_screen_texture || state.used_sss || env->ssao_enabled || env->ssr_enabled); //only enable MRT rendering if any of these is enabled + use_mrt = env && (state.used_sss || env->ssao_enabled || env->ssr_enabled); //only enable MRT rendering if any of these is enabled //effects disabled and transparency also prevent using MRTs use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]; use_mrt = use_mrt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]; @@ -4156,6 +4157,20 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const if (use_mrt) { _render_mrts(env, p_cam_projection); + } else { + //FIXME: check that this is possible to use + if (state.used_screen_texture) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + _blur_effect_buffer(); + //restored framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + } } if (state.used_screen_texture) { @@ -4233,7 +4248,11 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const storage->canvas->canvas_begin(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, env_radiance_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 8b86316da8..036ff58719 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1260,6 +1260,10 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //need this for proper sampling if (config.srgb_decode_supported && texture->srgb && !texture->using_srgb) { @@ -1377,8 +1381,8 @@ void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo); glDeleteFramebuffers(1, &tmp_fb); diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 88a97a04aa..10a803cafe 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -219,9 +219,8 @@ void main() { N.z = 0.5 - 0.5*((N.x * N.x) + (N.y * N.y)); N = normalize(N); - if (!z_flip) { - //N.y=-N.y; //y is flipped to improve blending between both sides - } else { + if (z_flip) { + N.y=-N.y; //y is flipped to improve blending between both sides N.z=-N.z; } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index f94ca6fcba..29623a6296 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -429,7 +429,9 @@ vec3 textureDualParaboloid(sampler2DArray p_tex, vec3 p_vec,float p_roughness) { // we need to lie the derivatives (normg) and assume that DP side is always the same // to get proper texure filtering vec2 normg=norm.xy; - norm.y+=max(0.0,sign(norm.z))*0.5; + if (norm.z>0) { + norm.y=0.5-norm.y+0.5; + } // thanks to OpenGL spec using floor(layer + 0.5) for texture arrays, // it's easy to have precision errors using fract() to interpolate layers @@ -451,7 +453,9 @@ vec3 textureDualParaboloid(sampler2D p_tex, vec3 p_vec,float p_roughness) { vec3 norm = normalize(p_vec); norm.xy/=1.0+abs(norm.z); norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25); - norm.y+=max(0.0,sign(norm.z))*0.5; + if (norm.z>0) { + norm.y=0.5-norm.y+0.5; + } return textureLod(p_tex, norm.xy, p_roughness * RADIANCE_MAX_LOD).xyz; } @@ -964,12 +968,12 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex; float light_length = length( light_rel_vec ); float normalized_distance = light_length*spot_lights[idx].light_pos_inv_radius.w; - vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), spot_lights[idx].light_direction_attenuation.w )); + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.001), spot_lights[idx].light_direction_attenuation.w )); vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; float spot_cutoff=spot_lights[idx].light_params.y; float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff); float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff); - light_attenuation *= 1.0 - pow( spot_rim, spot_lights[idx].light_params.x); + light_attenuation *= 1.0 - pow( max(spot_rim,0.001), spot_lights[idx].light_params.x); if (spot_lights[idx].light_params.w>0.5) { //there is a shadowmap diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 7f91cc86cf..5bf2da9912 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -554,10 +554,10 @@ static void _generate_tangents_and_binormals(const PoolVector<int> &p_indices, c tangent = Vector3(); } else { tangent = Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r) + (t2 * z1 - t1 * z2) * r) .normalized(); binormal = Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r) + (s1 * z2 - s2 * z1) * r) .normalized(); } @@ -920,8 +920,6 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me bn.z = -bn.z; vertex.tangent.d = vertex.normal.cross(vertex.tangent.normal).dot(bn) > 0 ? 1 : -1; - - print_line("Tangent " + itos(p_i) + ": " + vertex.tangent); } #endif diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 7c6b233bd4..7ce884a455 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -199,6 +199,25 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) { undo_redo->add_undo_method(n2dc, "set_global_position", n2dc->get_global_position()); } } + + Control *cnt = E->get()->cast_to<Control>(); + if (cnt) { + + Vector2 old_pivot = cnt->get_pivot_offset(); + Vector2 new_pivot = cnt->get_global_transform_with_canvas().affine_inverse().xform(mouse_pos); + Vector2 old_pos = cnt->get_position(); + + Vector2 top_pos = cnt->get_transform().get_origin(); //remember where top pos was + cnt->set_pivot_offset(new_pivot); + Vector2 new_top_pos = cnt->get_transform().get_origin(); //check where it is now + + Vector2 new_pos = old_pos - (new_top_pos - top_pos); //offset it back + + undo_redo->add_do_method(cnt, "set_pivot_offset", new_pivot); + undo_redo->add_do_method(cnt, "set_position", new_pos); + undo_redo->add_undo_method(cnt, "set_pivot_offset", old_pivot); + undo_redo->add_undo_method(cnt, "set_position", old_pos); + } } undo_redo->commit_action(); @@ -842,6 +861,8 @@ void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) { se->undo_state = canvas_item->edit_get_state(); if (canvas_item->cast_to<Node2D>()) se->undo_pivot = canvas_item->cast_to<Node2D>()->edit_get_pivot(); + if (canvas_item->cast_to<Control>()) + se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); } if (selection.size() == 1 && selection[0]->cast_to<Node2D>()) { @@ -1149,6 +1170,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { canvas_item->edit_set_state(se->undo_state); if (canvas_item->cast_to<Node2D>()) canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot); + if (canvas_item->cast_to<Control>()) + canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot); } } @@ -1238,12 +1261,18 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { Variant state = canvas_item->edit_get_state(); undo_redo->add_do_method(canvas_item, "edit_set_state", state); undo_redo->add_undo_method(canvas_item, "edit_set_state", se->undo_state); - if (canvas_item->cast_to<Node2D>()) { + { Node2D *pvt = canvas_item->cast_to<Node2D>(); - if (pvt->edit_has_pivot()) { + if (pvt && pvt->edit_has_pivot()) { undo_redo->add_do_method(canvas_item, "edit_set_pivot", pvt->edit_get_pivot()); undo_redo->add_undo_method(canvas_item, "edit_set_pivot", se->undo_pivot); } + + Control *cnt = canvas_item->cast_to<Control>(); + if (cnt) { + undo_redo->add_do_method(canvas_item, "set_pivot_offset", cnt->get_pivot_offset()); + undo_redo->add_undo_method(canvas_item, "set_pivot_offset", se->undo_pivot); + } } } undo_redo->commit_action(); @@ -1380,7 +1409,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { if (canvas_item->cast_to<Node2D>()) se->undo_pivot = canvas_item->cast_to<Node2D>()->edit_get_pivot(); if (canvas_item->cast_to<Control>()) - se->undo_pivot = Vector2(); + se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); return; } @@ -1405,6 +1434,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { se->undo_state = canvas_item->edit_get_state(); if (canvas_item->cast_to<Node2D>()) se->undo_pivot = canvas_item->cast_to<Node2D>()->edit_get_pivot(); + if (canvas_item->cast_to<Control>()) + se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); return; } @@ -1522,6 +1553,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { canvas_item->edit_set_state(se->undo_state); //reset state and reapply if (canvas_item->cast_to<Node2D>()) canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot); + if (canvas_item->cast_to<Control>()) + canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot); } Vector2 dfrom = drag_from; @@ -1659,6 +1692,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { Node2D *n2d = canvas_item->cast_to<Node2D>(); n2d->edit_set_pivot(se->undo_pivot + drag_vector); } + if (canvas_item->cast_to<Control>()) { + canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot + drag_vector); + } continue; } break; case DRAG_NODE_2D: { @@ -1920,6 +1956,14 @@ void CanvasItemEditor::_viewport_draw() { pivot_found = true; } } + if (canvas_item->cast_to<Control>()) { + Vector2 pivot_ofs = canvas_item->cast_to<Control>()->get_pivot_offset(); + if (pivot_ofs != Vector2()) { + viewport->draw_texture(pivot, xform.xform(pivot_ofs) + (-pivot->get_size() / 2).floor()); + } + can_move_pivot = true; + pivot_found = true; + } if (tool == TOOL_SELECT) { @@ -2108,10 +2152,16 @@ void CanvasItemEditor::_notification(int p_what) { Transform2D xform = canvas_item->get_transform(); - if (r != se->prev_rect || xform != se->prev_xform) { + Vector2 pivot; + if (canvas_item->cast_to<Control>()) { + pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); + } + + if (r != se->prev_rect || xform != se->prev_xform || pivot != se->prev_pivot) { viewport->update(); se->prev_rect = r; se->prev_xform = xform; + se->prev_pivot = pivot; } } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 22fa5b5db8..702deb51f9 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -56,6 +56,7 @@ public: Transform2D prev_xform; float prev_rot; Rect2 prev_rect; + Vector2 prev_pivot; CanvasItemEditorSelectedItem() { prev_rot = 0; } }; diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index c74eaf21a1..2d05c8eba1 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -874,7 +874,7 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) { Color bg_color(0.1, 0.1, 0.1, 1.0); for (int i = 0; i < thumbnail_size; i++) { for (int j = 0; j < thumbnail_size; j++) { - im.put_pixel(i, j, bg_color); + im.set_pixel(i, j, bg_color); } } @@ -890,7 +890,7 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) { // Plot point if (y >= 0 && y < im.get_height()) { - im.put_pixel(x, y, line_color); + im.set_pixel(x, y, line_color); } // Plot vertical line to fix discontinuity (not 100% correct but enough for a preview) @@ -904,7 +904,7 @@ Ref<Texture> CurvePreviewGenerator::generate(const Ref<Resource> &p_from) { y1 = y; } for (int ly = y0; ly < y1; ++ly) { - im.put_pixel(x, ly, line_color); + im.set_pixel(x, ly, line_color); } } diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 11d804422a..7f8581535c 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -431,7 +431,7 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) { for (int i = 0; i < thumbnail_size; i++) { for (int j = 0; j < thumbnail_size; j++) { - img->put_pixel(i, j, bg_color); + img->set_pixel(i, j, bg_color); } } @@ -469,8 +469,8 @@ Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) { Color ul = color; ul.a *= 0.5; - img->put_pixel(col, line * 2, bg_color.blend(ul)); - img->put_pixel(col, line * 2 + 1, color); + img->set_pixel(col, line * 2, bg_color.blend(ul)); + img->set_pixel(col, line * 2 + 1, color); prev_is_text = _is_text_char(c); } diff --git a/editor/plugins/shader_graph_editor_plugin.cpp b/editor/plugins/shader_graph_editor_plugin.cpp index 9c65ef667a..5506c035ec 100644 --- a/editor/plugins/shader_graph_editor_plugin.cpp +++ b/editor/plugins/shader_graph_editor_plugin.cpp @@ -1382,7 +1382,7 @@ ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int Color c = graph->default_get_value(type,p_id,param); for (int x=1;x<14;x++) for (int y=1;y<14;y++) - icon_color.put_pixel(x,y,c); + icon_color.set_pixel(x,y,c); Ref<ImageTexture> t; t.instance(); t->create_from_image(icon_color); diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp index d9daffc59e..353bd1274a 100644 --- a/modules/etc/image_etc.cpp +++ b/modules/etc/image_etc.cpp @@ -153,6 +153,9 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f Etc::Image::Format etc2comp_etc_format = _image_format_to_etc2comp_format(etc_format); int wofs = 0; + + print_line("begin encoding, format: " + Image::get_format_name(etc_format)); + uint64_t t = OS::get_singleton()->get_ticks_msec(); for (int i = 0; i < mmc + 1; i++) { // convert source image to internal etc2comp format (which is equivalent to Image::FORMAT_RGBAF) // NOTE: We can alternatively add a case to Image::convert to handle Image::FORMAT_RGBAF conversion. @@ -177,6 +180,7 @@ static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_f delete[] etc_data; delete[] src_rgba_f; } + print_line("time encoding: " + rtos(OS::get_singleton()->get_ticks_msec() - t)); p_img->create(imgw, imgh, mmc > 1 ? true : false, etc_format, dst_data); } diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp new file mode 100644 index 0000000000..ec8470518a --- /dev/null +++ b/platform/iphone/export/export.cpp @@ -0,0 +1,345 @@ +/*************************************************************************/ +/* export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "export.h" +#include "editor/editor_export.h" +#include "editor/editor_node.h" +#include "editor/editor_settings.h" +#include "global_config.h" +#include "io/marshalls.h" +#include "io/resource_saver.h" +#include "io/zip_io.h" +#include "os/file_access.h" +#include "os/os.h" +#include "platform/osx/logo.gen.h" +#include "string.h" +#include "version.h" + +#include <sys/stat.h> + +class EditorExportPlatformIOS : public EditorExportPlatform { + + GDCLASS(EditorExportPlatformIOS, EditorExportPlatform); + + int version_code; + + Ref<ImageTexture> logo; + + void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary); + +protected: + virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features); + virtual void get_export_options(List<ExportOption> *r_options); + +public: + virtual String get_name() const { return "iOS"; } + virtual Ref<Texture> get_logo() const { return logo; } + + virtual String get_binary_extension() const { return "xcodeproj"; } + virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0); + + virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const; + + EditorExportPlatformIOS(); + ~EditorExportPlatformIOS(); +}; + +void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) { + + // what does this need to do? +} + +void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) { + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "zip"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "zip"), "")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); + // r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "png"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier"), "org.godotengine.iosgame")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "godotiosgame")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 1)); + + /* probably need some more info */ +} + +void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary) { + + String str; + String strnew; + str.parse_utf8((const char *)pfile.ptr(), pfile.size()); + Vector<String> lines = str.split("\n"); + for (int i = 0; i < lines.size(); i++) { + if (lines[i].find("$binary") != -1) { + strnew += lines[i].replace("$binary", p_binary) + "\n"; + } else if (lines[i].find("$name") != -1) { + strnew += lines[i].replace("$name", p_name) + "\n"; + } else if (lines[i].find("$info") != -1) { + strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n"; + } else if (lines[i].find("$identifier") != -1) { + strnew += lines[i].replace("$identifier", p_preset->get("application/identifier")) + "\n"; + } else if (lines[i].find("$short_version") != -1) { + strnew += lines[i].replace("$short_version", p_preset->get("application/short_version")) + "\n"; + } else if (lines[i].find("$version") != -1) { + strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n"; + } else if (lines[i].find("$signature") != -1) { + strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n"; + } else if (lines[i].find("$copyright") != -1) { + strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n"; + } else { + strnew += lines[i] + "\n"; + } + } + + // !BAS! I'm assuming the 9 in the original code was a typo. I've added -1 or else it seems to also be adding our terminating zero... + // should apply the same fix in our OSX export. + CharString cs = strnew.utf8(); + pfile.resize(cs.size() - 1); + for (int i = 0; i < cs.size() - 1; i++) { + pfile[i] = cs[i]; + } +} + +Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + String src_pkg_name; + String dest_dir = p_path.get_base_dir() + "/"; + String binary_name = p_path.get_file().get_basename(); + + EditorProgress ep("export", "Exporting for iOS", 3); + + if (p_debug) + src_pkg_name = p_preset->get("custom_package/debug"); + else + src_pkg_name = p_preset->get("custom_package/release"); + + if (src_pkg_name == "") { + String err; + src_pkg_name = find_export_template("iphone.zip", &err); + if (src_pkg_name == "") { + EditorNode::add_io_error(err); + return ERR_FILE_NOT_FOUND; + } + } + + FileAccess *src_f = NULL; + zlib_filefunc_def io = zipio_create_io_from_file(&src_f); + + ep.step("Creating app", 0); + + unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io); + if (!src_pkg_zip) { + + EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name); + return ERR_FILE_NOT_FOUND; + } + + ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN); + int ret = unzGoToFirstFile(src_pkg_zip); + + String binary_to_use = "godot.iphone." + String(p_debug ? "debug" : "release") + "."; + int bits_mode = p_preset->get("application/bits_mode"); + binary_to_use += String(bits_mode == 0 ? "fat" : bits_mode == 1 ? "arm64" : "armv7"); + + print_line("binary: " + binary_to_use); + String pkg_name; + if (p_preset->get("application/name") != "") + pkg_name = p_preset->get("application/name"); // app_name + else if (String(GlobalConfig::get_singleton()->get("application/name")) != "") + pkg_name = String(GlobalConfig::get_singleton()->get("application/name")); + else + pkg_name = "Unnamed"; + + DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); + ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE) + + /* Now process our template */ + bool found_binary = false; + int total_size = 0; + + while (ret == UNZ_OK) { + bool is_execute = false; + + //get filename + unz_file_info info; + char fname[16384]; + ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, NULL, 0, NULL, 0); + + String file = fname; + + print_line("READ: " + file); + Vector<uint8_t> data; + data.resize(info.uncompressed_size); + + //read + unzOpenCurrentFile(src_pkg_zip); + unzReadCurrentFile(src_pkg_zip, data.ptr(), data.size()); + unzCloseCurrentFile(src_pkg_zip); + + //write + + file = file.replace_first("iphone/", ""); + + if (file == "godot_ios.xcodeproj/project.pbxproj") { + print_line("parse pbxproj"); + _fix_config_file(p_preset, data, pkg_name, binary_name); + } else if (file == "godot_ios/godot_ios-Info.plist") { + print_line("parse plist"); + _fix_config_file(p_preset, data, pkg_name, binary_name); + } else if (file.begins_with("godot.iphone")) { + if (file != binary_to_use) { + ret = unzGoToNextFile(src_pkg_zip); + continue; //ignore! + } + found_binary = true; + is_execute = true; + file = "godot_ios.iphone"; + } + + ///@TODO need to parse logo files + + if (data.size() > 0) { + file = file.replace("godot_ios", binary_name); + + print_line("ADDING: " + file + " size: " + itos(data.size())); + total_size += data.size(); + + /* write it into our folder structure */ + file = dest_dir + file; + + /* make sure this folder exists */ + String dir_name = file.get_base_dir(); + if (!tmp_app_path->dir_exists(dir_name)) { + print_line("Creating " + dir_name); + Error dir_err = tmp_app_path->make_dir_recursive(dir_name); + if (dir_err) { + ERR_PRINTS("Can't create '" + dir_name + "'."); + unzClose(src_pkg_zip); + return ERR_CANT_CREATE; + } + } + + /* write the file */ + FileAccess *f = FileAccess::open(file, FileAccess::WRITE); + if (!f) { + ERR_PRINTS("Can't write '" + file + "'."); + unzClose(src_pkg_zip); + return ERR_CANT_CREATE; + }; + f->store_buffer(data.ptr(), data.size()); + f->close(); + memdelete(f); + + if (is_execute) { + // we need execute rights on this file + chmod(file.utf8().get_data(), 0755); + } + } + + ret = unzGoToNextFile(src_pkg_zip); + } + + /* we're done with our source zip */ + unzClose(src_pkg_zip); + + if (!found_binary) { + ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive."); + unzClose(src_pkg_zip); + return ERR_FILE_NOT_FOUND; + } + + ep.step("Making PKG", 1); + + String pack_path = dest_dir + binary_name + ".pck"; + Error err = save_pack(p_preset, pack_path); + + if (err) { + return err; + } + +#ifdef OSX_ENABLED + /* and open up xcode with our new project.... */ + List<String> args; + args.push_back(p_path); + err = OS::get_singleton()->execute("/usr/bin/open", args, false); + ERR_FAIL_COND_V(err, err); + +#endif + + return OK; +} + +bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { + + bool valid = true; + String err; + + if (!exists_export_template("iphone.zip", &err)) { + valid = false; + } + + if (p_preset->get("custom_package/debug") != "" && !FileAccess::exists(p_preset->get("custom_package/debug"))) { + valid = false; + err += "Custom debug package not found.\n"; + } + + if (p_preset->get("custom_package/release") != "" && !FileAccess::exists(p_preset->get("custom_package/release"))) { + valid = false; + err += "Custom release package not found.\n"; + } + + if (!err.empty()) + r_error = err; + + return valid; +} + +EditorExportPlatformIOS::EditorExportPlatformIOS() { + + ///@TODO need to create the correct logo + // Ref<Image> img = memnew(Image(_iphone_logo)); + Ref<Image> img = memnew(Image(_osx_logo)); + logo.instance(); + logo->create_from_image(img); +} + +EditorExportPlatformIOS::~EditorExportPlatformIOS() { +} + +void register_iphone_exporter() { + + Ref<EditorExportPlatformIOS> platform; + platform.instance(); + + EditorExport::get_singleton()->add_export_platform(platform); +} diff --git a/platform/iphone/export/export.h b/platform/iphone/export/export.h new file mode 100644 index 0000000000..6e9324aed7 --- /dev/null +++ b/platform/iphone/export/export.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +void register_iphone_exporter(); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 9d3493cb49..c81fb00b36 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -185,8 +185,8 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset } CharString cs = strnew.utf8(); - plist.resize(cs.size()); - for (int i = 9; i < cs.size(); i++) { + plist.resize(cs.size() - 1); + for (int i = 0; i < cs.size() - 1; i++) { plist[i] = cs[i]; } } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index fd261117e1..8b2653f639 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -554,11 +554,12 @@ real_t RigidBody2D::get_inertia() const { void RigidBody2D::set_weight(real_t p_weight) { - set_mass(p_weight / 9.8); + set_mass(p_weight / real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10); } + real_t RigidBody2D::get_weight() const { - return mass * 9.8; + return mass * real_t(GLOBAL_DEF("physics/2d/default_gravity", 98)) / 10; } void RigidBody2D::set_friction(real_t p_friction) { diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 2a7a804470..718daab75a 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -520,11 +520,11 @@ real_t RigidBody::get_mass() const { void RigidBody::set_weight(real_t p_weight) { - set_mass(p_weight / 9.8); + set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); } real_t RigidBody::get_weight() const { - return mass * 9.8; + return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); } void RigidBody::set_friction(real_t p_friction) { diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 92bb5d43a7..2a96f8260c 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -95,13 +95,25 @@ void Container::fit_child_in_rect(Control *p_child, const Rect2 &p_rect) { Rect2 r = p_rect; if (!(p_child->get_h_size_flags() & SIZE_FILL)) { - r.size.x = minsize.x; - r.position.x += Math::floor((p_rect.size.x - minsize.x) / 2); + r.size.x = minsize.width; + if (p_child->get_h_size_flags() & SIZE_SHRINK_END) { + r.position.x += p_rect.size.width - minsize.width; + } else if (p_child->get_h_size_flags() & SIZE_SHRINK_CENTER) { + r.position.x += Math::floor((p_rect.size.x - minsize.width) / 2); + } else { + r.position.x += 0; + } } if (!(p_child->get_v_size_flags() & SIZE_FILL)) { r.size.y = minsize.y; - r.position.y += Math::floor((p_rect.size.y - minsize.y) / 2); + if (p_child->get_v_size_flags() & SIZE_SHRINK_END) { + r.position.y += p_rect.size.height - minsize.height; + } else if (p_child->get_v_size_flags() & SIZE_SHRINK_CENTER) { + r.position.y += Math::floor((p_rect.size.y - minsize.height) / 2); + } else { + r.position.y += 0; + } } for (int i = 0; i < 4; i++) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 45485b768e..bf8d81d4a6 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -90,11 +90,22 @@ Size2 Control::edit_get_minimum_size() const { return get_combined_minimum_size(); } +Transform2D Control::_get_internal_transform() const { + + Transform2D rot_scale; + rot_scale.set_rotation_and_scale(data.rotation, data.scale); + Transform2D offset; + offset.set_origin(-data.pivot_offset); + + return offset.affine_inverse() * (rot_scale * offset); +} void Control::edit_set_rect(const Rect2 &p_edit_rect) { - Transform2D postxf; - postxf.set_rotation_and_scale(data.rotation, data.scale); - Vector2 new_pos = postxf.xform(p_edit_rect.position); + Transform2D xform = _get_internal_transform(); + + // xform[2] += get_position(); + + Vector2 new_pos = xform.basis_xform(p_edit_rect.position); Vector2 pos = get_position() + new_pos; @@ -353,8 +364,9 @@ void Control::remove_child_notify(Node *p_child) { void Control::_update_canvas_item_transform() { - Transform2D xform = Transform2D(data.rotation, get_position()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } @@ -1219,10 +1231,26 @@ void Control::_size_changed() { Point2 new_pos_cache = Point2(margin_pos[0], margin_pos[1]).floor(); Size2 new_size_cache = Point2(margin_pos[2], margin_pos[3]).floor() - new_pos_cache; + Size2 minimum_size = get_combined_minimum_size(); - new_size_cache.x = MAX(minimum_size.x, new_size_cache.x); - new_size_cache.y = MAX(minimum_size.y, new_size_cache.y); + if (data.h_grow == GROW_DIRECTION_BEGIN) { + if (minimum_size.width > new_size_cache.width) { + new_pos_cache.x = new_pos_cache.x + new_size_cache.width - minimum_size.width; + new_size_cache.width = minimum_size.width; + } + } else { + new_size_cache.width = MAX(minimum_size.width, new_size_cache.width); + } + + if (data.v_grow == GROW_DIRECTION_BEGIN) { + if (minimum_size.height > new_size_cache.height) { + new_pos_cache.y = new_pos_cache.y + new_size_cache.height - minimum_size.height; + new_size_cache.height = minimum_size.height; + } + } else { + new_size_cache.height = MAX(minimum_size.height, new_size_cache.height); + } bool pos_changed = new_pos_cache != data.pos_cache; bool size_changed = new_size_cache != data.size_cache; @@ -1887,8 +1915,8 @@ Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const { Transform2D Control::get_transform() const { - Transform2D xform = Transform2D(data.rotation, get_position()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); return xform; } @@ -2214,6 +2242,19 @@ void Control::_font_changed() { minimum_size_changed(); //fonts affect minimum size pretty much almost always } +void Control::set_pivot_offset(const Vector2 &p_pivot) { + + data.pivot_offset = p_pivot; + update(); + _notify_transform(); + _change_notify("rect_pivot_offset"); +} + +Vector2 Control::get_pivot_offset() const { + + return data.pivot_offset; +} + void Control::set_scale(const Vector2 &p_scale) { data.scale = p_scale; @@ -2300,6 +2341,27 @@ bool Control::is_clipping_contents() { return data.clip_contents; } +void Control::set_h_grow_direction(GrowDirection p_direction) { + + data.h_grow = p_direction; + _size_changed(); +} + +Control::GrowDirection Control::get_h_grow_direction() const { + + return data.h_grow; +} + +void Control::set_v_grow_direction(GrowDirection p_direction) { + + data.v_grow = p_direction; + _size_changed(); +} +Control::GrowDirection Control::get_v_grow_direction() const { + + return data.v_grow; +} + void Control::_bind_methods() { //ClassDB::bind_method(D_METHOD("_window_resize_event"),&Control::_window_resize_event); @@ -2325,6 +2387,7 @@ void Control::_bind_methods() { // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale); + ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset); ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin); ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin); ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end); @@ -2335,6 +2398,7 @@ void Control::_bind_methods() { // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg); ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale); + ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset); ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size); ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size); ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position); @@ -2388,6 +2452,12 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("get_parent_control:Control"), &Control::get_parent_control); + ClassDB::bind_method(D_METHOD("set_h_grow_direction", "direction"), &Control::set_h_grow_direction); + ClassDB::bind_method(D_METHOD("get_h_grow_direction"), &Control::get_h_grow_direction); + + ClassDB::bind_method(D_METHOD("set_v_grow_direction", "direction"), &Control::set_v_grow_direction); + ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction); + ClassDB::bind_method(D_METHOD("set_tooltip", "tooltip"), &Control::set_tooltip); ClassDB::bind_method(D_METHOD("get_tooltip", "atpos"), &Control::get_tooltip, DEFVAL(Point2())); ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip); @@ -2438,12 +2508,17 @@ void Control::_bind_methods() { ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_right", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_RIGHT); ADD_PROPERTYINZ(PropertyInfo(Variant::INT, "margin_bottom", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_BOTTOM); + ADD_GROUP("Grow Direction", "grow_"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End"), "set_h_grow_direction", "get_h_grow_direction"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End"), "set_v_grow_direction", "get_v_grow_direction"); + ADD_GROUP("Rect", "rect_"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_deg", "get_rotation_deg"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); + ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); @@ -2459,8 +2534,8 @@ void Control::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter"); ADD_GROUP("Size Flags", "size_flags_"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_h_size_flags", "get_h_size_flags"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand"), "set_v_size_flags", "get_v_size_flags"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags"); + ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_v_size_flags", "get_v_size_flags"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), "set_stretch_ratio", "get_stretch_ratio"); ADD_GROUP("Theme", ""); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); @@ -2502,11 +2577,16 @@ void Control::_bind_methods() { BIND_CONSTANT(SIZE_EXPAND); BIND_CONSTANT(SIZE_FILL); BIND_CONSTANT(SIZE_EXPAND_FILL); + BIND_CONSTANT(SIZE_SHRINK_CENTER); + BIND_CONSTANT(SIZE_SHRINK_END); BIND_CONSTANT(MOUSE_FILTER_STOP); BIND_CONSTANT(MOUSE_FILTER_PASS); BIND_CONSTANT(MOUSE_FILTER_IGNORE); + BIND_CONSTANT(GROW_DIRECTION_BEGIN); + BIND_CONSTANT(GROW_DIRECTION_END); + ADD_SIGNAL(MethodInfo("resized")); ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "ev", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("mouse_entered")); @@ -2543,6 +2623,8 @@ Control::Control() { data.modal_frame = 0; data.block_minimum_size_adjust = false; data.disable_visibility_clip = false; + data.h_grow = GROW_DIRECTION_END; + data.v_grow = GROW_DIRECTION_END; data.clip_contents = false; for (int i = 0; i < 4; i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index 5834d1550a..86cf8f6dbd 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -57,6 +57,11 @@ public: ANCHOR_CENTER, }; + enum GrowDirection { + GROW_DIRECTION_BEGIN, + GROW_DIRECTION_END + }; + enum FocusMode { FOCUS_NONE, FOCUS_CLICK, @@ -67,7 +72,9 @@ public: SIZE_FILL = 1, SIZE_EXPAND = 2, - SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL + SIZE_EXPAND_FILL = SIZE_EXPAND | SIZE_FILL, + SIZE_SHRINK_CENTER = 4, //ignored by expand or fill + SIZE_SHRINK_END = 8, //ignored by expand or fil }; @@ -117,9 +124,12 @@ private: float margin[4]; AnchorType anchor[4]; FocusMode focus_mode; + GrowDirection h_grow; + GrowDirection v_grow; float rotation; Vector2 scale; + Vector2 pivot_offset; bool pending_resize; @@ -200,6 +210,8 @@ private: void _update_canvas_item_transform(); + Transform2D _get_internal_transform() const; + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); @@ -273,6 +285,12 @@ public: void set_begin(const Point2 &p_point); // helper void set_end(const Point2 &p_point); // helper + void set_h_grow_direction(GrowDirection p_direction); + GrowDirection get_h_grow_direction() const; + + void set_v_grow_direction(GrowDirection p_direction); + GrowDirection get_v_grow_direction() const; + float get_margin(Margin p_margin) const; Point2 get_begin() const; Point2 get_end() const; @@ -293,6 +311,9 @@ public: float get_rotation() const; float get_rotation_deg() const; + void set_pivot_offset(const Vector2 &p_pivot); + Vector2 get_pivot_offset() const; + void set_scale(const Vector2 &p_scale); Vector2 get_scale() const; @@ -409,5 +430,6 @@ VARIANT_ENUM_CAST(Control::FocusMode); VARIANT_ENUM_CAST(Control::SizeFlags); VARIANT_ENUM_CAST(Control::CursorShape); VARIANT_ENUM_CAST(Control::MouseFilter); +VARIANT_ENUM_CAST(Control::GrowDirection); #endif diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 36d2a38b3d..9ec89e4003 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -32,7 +32,6 @@ #include "servers/visual_server.h" //#include "servers/spatial_sound_2d_server.h" #include "global_config.h" -#include "global_config.h" #include "scene/2d/camera_2d.h" #include "scene/2d/visibility_notifier_2d.h" #include "scene/main/viewport.h" |