Skip to content

Commit

Permalink
Ability to make CanvasLayers have pseudo 3D depth.
Browse files Browse the repository at this point in the history
  • Loading branch information
reduz committed Apr 5, 2019
1 parent 4141703 commit 19a6a62
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 5 deletions.
11 changes: 11 additions & 0 deletions editor/plugins/canvas_item_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4150,6 +4150,14 @@ void CanvasItemEditor::_popup_callback(int p_op) {

_focus_selection(p_op);

} break;
case PREVIEW_CANVAS_SCALE: {

bool preview = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE));
preview = !preview;
VS::get_singleton()->canvas_set_disable_scale(!preview);
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE), preview);

} break;
case SKELETON_MAKE_BONES: {

Expand Down Expand Up @@ -4824,6 +4832,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/preview_canvas_scale", TTR("Preview Canvas Scale"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_P), PREVIEW_CANVAS_SCALE);

presets_menu = memnew(MenuButton);
presets_menu->set_text(TTR("Layout"));
Expand Down Expand Up @@ -5421,6 +5431,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
label_desc->add_constant_override("line_spacing", 0);
label_desc->hide();
editor->get_gui_base()->add_child(label_desc);
VS::get_singleton()->canvas_set_disable_scale(true);
}

CanvasItemEditorViewport::~CanvasItemEditorViewport() {
Expand Down
1 change: 1 addition & 0 deletions editor/plugins/canvas_item_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class CanvasItemEditor : public VBoxContainer {
ANIM_CLEAR_POSE,
VIEW_CENTER_TO_SELECTION,
VIEW_FRAME_TO_SELECTION,
PREVIEW_CANVAS_SCALE,
SKELETON_MAKE_BONES,
SKELETON_CLEAR_BONES,
SKELETON_SHOW_BONES,
Expand Down
2 changes: 1 addition & 1 deletion scene/2d/parallax_background.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ void ParallaxBackground::_bind_methods() {
ParallaxBackground::ParallaxBackground() {

scale = 1.0;
set_layer(-1); //behind all by default
set_layer(-100); //behind all by default

base_scale = Vector2(1, 1);
ignore_camera_zoom = false;
Expand Down
51 changes: 51 additions & 0 deletions scene/main/canvas_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,15 @@ void CanvasLayer::_notification(int p_what) {
VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
_update_follow_viewport();

} break;
case NOTIFICATION_EXIT_TREE: {

vp->_canvas_layer_remove(this);
VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
viewport = RID();
_update_follow_viewport(false);

} break;
case NOTIFICATION_MOVED_IN_PARENT: {
Expand Down Expand Up @@ -235,6 +237,41 @@ RID CanvasLayer::get_canvas() const {

return canvas;
}

void CanvasLayer::set_follow_viewport(bool p_enable) {
if (follow_viewport == p_enable) {
return;
}

follow_viewport = p_enable;
_update_follow_viewport();
}

bool CanvasLayer::is_following_viewport() const {
return follow_viewport;
}

void CanvasLayer::set_follow_viewport_scale(float p_ratio) {
follow_viewport_scale = p_ratio;
_update_follow_viewport();
}

float CanvasLayer::get_follow_viewport_scale() const {
return follow_viewport_scale;
}

void CanvasLayer::_update_follow_viewport(bool p_force_exit) {

if (!is_inside_tree()) {
return;
}
if (p_force_exit || !follow_viewport) {
VS::get_singleton()->canvas_set_parent(canvas, RID(), 1.0);
} else {
VS::get_singleton()->canvas_set_parent(canvas, vp->get_world_2d()->get_canvas(), follow_viewport_scale);
}
}

void CanvasLayer::_bind_methods() {

ClassDB::bind_method(D_METHOD("set_layer", "layer"), &CanvasLayer::set_layer);
Expand All @@ -255,18 +292,30 @@ void CanvasLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &CanvasLayer::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &CanvasLayer::get_scale);

ClassDB::bind_method(D_METHOD("set_follow_viewport", "enable"), &CanvasLayer::set_follow_viewport);
ClassDB::bind_method(D_METHOD("is_following_viewport"), &CanvasLayer::is_following_viewport);

ClassDB::bind_method(D_METHOD("set_follow_viewport_scale", "scale"), &CanvasLayer::set_follow_viewport_scale);
ClassDB::bind_method(D_METHOD("get_follow_viewport_scale"), &CanvasLayer::get_follow_viewport_scale);

ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport"), &CanvasLayer::set_custom_viewport);
ClassDB::bind_method(D_METHOD("get_custom_viewport"), &CanvasLayer::get_custom_viewport);

ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasLayer::get_canvas);

ADD_GROUP("Layer", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer");
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation_degrees", PROPERTY_HINT_RANGE, "-1080,1080,0.1,or_lesser,or_greater", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform");
ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport");
ADD_GROUP("Follow Viewport", "follow_viewport");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_viewport_enable"), "set_follow_viewport", "is_following_viewport");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "follow_viewport_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,or_lesser"), "set_follow_viewport_scale", "get_follow_viewport_scale");
}

CanvasLayer::CanvasLayer() {
Expand All @@ -280,6 +329,8 @@ CanvasLayer::CanvasLayer() {
custom_viewport = NULL;
custom_viewport_id = 0;
sort_index = 0;
follow_viewport = false;
follow_viewport_scale = 1.0;
}

CanvasLayer::~CanvasLayer() {
Expand Down
10 changes: 10 additions & 0 deletions scene/main/canvas_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ class CanvasLayer : public Node {

int sort_index;

bool follow_viewport;
float follow_viewport_scale;

void _update_xform();
void _update_locrotscale();
void _update_follow_viewport(bool p_force_exit = false);

protected:
void _notification(int p_what);
Expand Down Expand Up @@ -91,6 +95,12 @@ class CanvasLayer : public Node {
void reset_sort_index();
int get_sort_index();

void set_follow_viewport(bool p_enable);
bool is_following_viewport() const;

void set_follow_viewport_scale(float p_ratio);
float get_follow_viewport_scale() const;

RID get_canvas() const;

CanvasLayer();
Expand Down
14 changes: 14 additions & 0 deletions servers/visual/visual_server_canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,19 @@ void VisualServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color)
canvas->modulate = p_color;
}

void VisualServerCanvas::canvas_set_disable_scale(bool p_disable) {
disable_scale = p_disable;
}

void VisualServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) {

Canvas *canvas = canvas_owner.get(p_canvas);
ERR_FAIL_COND(!canvas);

canvas->parent = p_parent;
canvas->parent_scale = p_scale;
}

RID VisualServerCanvas::canvas_item_create() {

Item *canvas_item = memnew(Item);
Expand Down Expand Up @@ -1434,4 +1447,5 @@ bool VisualServerCanvas::free(RID p_rid) {
}

VisualServerCanvas::VisualServerCanvas() {
disable_scale = false;
}
9 changes: 8 additions & 1 deletion servers/visual/visual_server_canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ class VisualServerCanvas {
bool children_order_dirty;
Vector<ChildItem> child_items;
Color modulate;
RID parent;
float parent_scale;

int find_item(Item *p_item) {
for (int i = 0; i < child_items.size(); i++) {
Expand All @@ -143,13 +145,16 @@ class VisualServerCanvas {
Canvas() {
modulate = Color(1, 1, 1, 1);
children_order_dirty = true;
parent_scale = 1.0;
}
};

RID_Owner<Canvas> canvas_owner;
mutable RID_Owner<Canvas> canvas_owner;
RID_Owner<Item> canvas_item_owner;
RID_Owner<RasterizerCanvas::Light> canvas_light_owner;

bool disable_scale;

private:
void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights);
void _render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
Expand All @@ -161,6 +166,8 @@ class VisualServerCanvas {
RID canvas_create();
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
void canvas_set_modulate(RID p_canvas, const Color &p_color);
void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
void canvas_set_disable_scale(bool p_disable);

RID canvas_item_create();
void canvas_item_set_parent(RID p_item, RID p_parent);
Expand Down
2 changes: 2 additions & 0 deletions servers/visual/visual_server_raster.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,8 @@ class VisualServerRaster : public VisualServer {
BIND0R(RID, canvas_create)
BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &)
BIND2(canvas_set_modulate, RID, const Color &)
BIND3(canvas_set_parent, RID, RID, float)
BIND1(canvas_set_disable_scale, bool)

BIND0R(RID, canvas_item_create)
BIND2(canvas_item_set_parent, RID, RID)
Expand Down
33 changes: 30 additions & 3 deletions servers/visual/visual_server_viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,33 @@
#include "visual_server_globals.h"
#include "visual_server_scene.h"

static Transform2D _canvas_get_transform(VisualServerViewport::Viewport *p_viewport, VisualServerCanvas::Canvas *p_canvas, VisualServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {

Transform2D xf = p_viewport->global_transform;

float scale = 1.0;
if (p_viewport->canvas_map.has(p_canvas->parent)) {
xf = xf * p_viewport->canvas_map[p_canvas->parent].transform;
scale = p_canvas->parent_scale;
}

xf = xf * p_canvas_data->transform;

if (scale != 1.0 && !VSG::canvas->disable_scale) {
Vector2 pivot = p_vp_size * 0.5;
Transform2D xfpivot;
xfpivot.set_origin(pivot);
Transform2D xfscale;
xfscale.scale(Vector2(scale, scale));

xf = xfpivot.affine_inverse() * xf;
xf = xfscale * xf;
xf = xfpivot * xf;
}

return xf;
}

void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {

/* Camera should always be BEFORE any other 3D */
Expand Down Expand Up @@ -86,10 +113,10 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E

for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {

Transform2D xf = p_viewport->global_transform * E->get().transform;

VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get().canvas);

Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);

//find lights in canvas

for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
Expand Down Expand Up @@ -193,7 +220,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E

VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas *>(E->get()->canvas);

Transform2D xform = p_viewport->global_transform * E->get()->transform;
Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);

RasterizerCanvas::Light *canvas_lights = NULL;

Expand Down
2 changes: 2 additions & 0 deletions servers/visual/visual_server_wrap_mt.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,8 @@ class VisualServerWrapMT : public VisualServer {
FUNCRID(canvas)
FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
FUNC2(canvas_set_modulate, RID, const Color &)
FUNC3(canvas_set_parent, RID, RID, float)
FUNC1(canvas_set_disable_scale, bool)

FUNCRID(canvas_item)
FUNC2(canvas_item_set_parent, RID, RID)
Expand Down
3 changes: 3 additions & 0 deletions servers/visual_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,9 @@ class VisualServer : public Object {
virtual RID canvas_create() = 0;
virtual void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) = 0;
virtual void canvas_set_modulate(RID p_canvas, const Color &p_color) = 0;
virtual void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) = 0;

virtual void canvas_set_disable_scale(bool p_disable) = 0;

virtual RID canvas_item_create() = 0;
virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0;
Expand Down

1 comment on commit 19a6a62

@davidwparker
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

Please sign in to comment.