diff options
| -rw-r--r-- | editor/SCsub | 31 | ||||
| -rw-r--r-- | editor/editor_name_dialog.cpp | 1 | ||||
| -rw-r--r-- | editor/editor_node.cpp | 115 | ||||
| -rw-r--r-- | editor/import/editor_import_collada.cpp | 8 | ||||
| -rw-r--r-- | editor/plugins/script_editor_plugin.cpp | 3 | ||||
| -rw-r--r-- | editor/scene_tree_dock.cpp | 132 | ||||
| -rw-r--r-- | editor/scene_tree_dock.h | 11 | ||||
| -rw-r--r-- | editor/scene_tree_editor.cpp | 167 | ||||
| -rw-r--r-- | editor/scene_tree_editor.h | 14 | ||||
| -rw-r--r-- | platform/osx/export/export.cpp | 343 | ||||
| -rw-r--r-- | scene/2d/node_2d.cpp | 2 | ||||
| -rw-r--r-- | scene/3d/mesh_instance.cpp | 78 | ||||
| -rw-r--r-- | scene/3d/mesh_instance.h | 2 | ||||
| -rw-r--r-- | scene/3d/spatial.cpp | 13 | ||||
| -rwxr-xr-x | scene/main/node.cpp | 98 | ||||
| -rw-r--r-- | scene/main/node.h | 19 | ||||
| -rw-r--r-- | scene/main/scene_tree.cpp | 18 | ||||
| -rw-r--r-- | scene/main/scene_tree.h | 1 | ||||
| -rw-r--r-- | scene/resources/material.cpp | 4 | ||||
| -rw-r--r-- | scene/resources/primitive_meshes.cpp | 36 | ||||
| -rw-r--r-- | servers/visual_server.cpp | 4 | 
21 files changed, 705 insertions, 395 deletions
diff --git a/editor/SCsub b/editor/SCsub index ffdeed1523..a26f6bba77 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -143,6 +143,9 @@ def make_translations_header(target, source, env):  def make_authors_header(target, source, env): +    sections = ["Project Founders", "Lead Developer", "Project Manager", "Developers"] +    sections_id = ["dev_founders", "dev_lead", "dev_manager", "dev_names"] +      src = source[0].srcnode().abspath      dst = target[0].srcnode().abspath      f = open(src, "rb") @@ -151,19 +154,35 @@ def make_authors_header(target, source, env):      g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")      g.write("#ifndef _EDITOR_AUTHORS_H\n")      g.write("#define _EDITOR_AUTHORS_H\n") -    g.write("static const char *dev_names[] = {\n") +    current_section = ""      name_count = -1 + +    def close_section(): +        g.write("\t0\n") +        g.write("};\n") +        g.write("#define " + current_section.upper() + "_COUNT " + str(name_count) + "\n") +      for line in f:          if name_count >= 0:              if line.startswith("    "):                  g.write("\t\"" + line.strip() + "\",\n")                  name_count += 1 -        elif line.strip() == "## Developers": -            name_count = 0 -    g.write("\t0\n") -    g.write("};\n") -    g.write("#define AUTHORS_COUNT " + str(name_count) + "\n") +                continue +        if line.startswith("## "): +            if name_count >= 0: +                close_section() +                name_count = -1 +            for i in range(len(sections)): +                if line.strip().endswith(sections[i]): +                    current_section = sections_id[i] +                    name_count = 0 +                    g.write("static const char *" + current_section + "[] = {\n") +                    break + +    if name_count >= 0: +        close_section() +      g.write("#endif\n")  if (env["tools"] == "yes"): diff --git a/editor/editor_name_dialog.cpp b/editor/editor_name_dialog.cpp index d4c418bfc9..7435e9a9f7 100644 --- a/editor/editor_name_dialog.cpp +++ b/editor/editor_name_dialog.cpp @@ -85,7 +85,6 @@ EditorNameDialog::EditorNameDialog() {  	add_child(makevb);  	name = memnew(LineEdit);  	makevb->add_child(name); -	makevb->move_child(name, get_label()->get_index() + 1);  	name->set_margin(MARGIN_TOP, 5);  	name->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 5);  	name->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 5); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 77050acd7c..2274690569 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2646,7 +2646,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {  			OS::get_singleton()->shell_open("https://godotengine.org/community");  		} break;  		case HELP_ABOUT: { -			about->popup_centered_minsize(Size2(500, 130) * EDSCALE); +			about->popup_centered_minsize(Size2(780, 500) * EDSCALE);  		} break;  		case SOURCES_REIMPORT: { @@ -6042,52 +6042,73 @@ EditorNode::EditorNode() {  	export_template_manager = memnew(ExportTemplateManager);  	gui_base->add_child(export_template_manager); -	about = memnew(AcceptDialog); -	about->set_title(TTR("Thanks from the Godot community!")); -	about->get_ok()->set_text(TTR("Thanks!")); -	about->set_hide_on_ok(true); -	gui_base->add_child(about); -	VBoxContainer *vbc = memnew(VBoxContainer); -	HBoxContainer *hbc = memnew(HBoxContainer); -	hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); -	hbc->set_alignment(BoxContainer::ALIGN_CENTER); -	about->add_child(vbc); -	vbc->add_child(hbc); -	Label *about_text = memnew(Label); -	about_text->set_text(VERSION_FULL_NAME + String::utf8("\n\u00A9 2007-2017 Juan Linietsky, Ariel Manzur.\n\u00A9 2014-2017 ") + TTR("Godot Engine contributors") + "\n"); -	TextureRect *logo = memnew(TextureRect); -	logo->set_texture(gui_base->get_icon("Logo", "EditorIcons")); -	hbc->add_child(logo); -	hbc->add_child(about_text); -	TabContainer *tc = memnew(TabContainer); -	tc->set_custom_minimum_size(Vector2(740, 300)); -	vbc->add_child(tc); -	ScrollContainer *dev_base = memnew(ScrollContainer); -	dev_base->set_name(TTR("Developers")); -	tc->add_child(dev_base); -	HBoxContainer *dev_hbc = memnew(HBoxContainer); -	dev_hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); -	dev_base->add_child(dev_hbc); -	for (int i = 0; i < 3; i++) { -		Label *dev_label = memnew(Label); -		dev_label->set_h_size_flags(Control::SIZE_EXPAND); -		dev_label->set_v_size_flags(Control::SIZE_FILL); -		dev_hbc->add_child(dev_label); -	} -	int dev_name_index = 0; -	int dev_name_column = 0; -	const int dev_index_max = AUTHORS_COUNT / 3 + (AUTHORS_COUNT % 3 == 0 ? 0 : 1); -	String dev_name = ""; -	const char **dev_names_ptr = dev_names; -	while (*dev_names_ptr) { -		dev_name += String::utf8(*dev_names_ptr++); -		if (++dev_name_index == dev_index_max || !*dev_names_ptr) { -			dev_hbc->get_child(dev_name_column)->cast_to<Label>()->set_text(dev_name); -			dev_name_column++; -			dev_name = ""; -			dev_name_index = 0; -		} else { -			dev_name += "\n"; +	{ + +		about = memnew(AcceptDialog); +		about->set_title(TTR("Thanks from the Godot community!")); +		about->get_ok()->set_text(TTR("Thanks!")); +		about->set_hide_on_ok(true); +		about->set_resizable(true); +		gui_base->add_child(about); + +		VBoxContainer *vbc = memnew(VBoxContainer); +		HBoxContainer *hbc = memnew(HBoxContainer); +		hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); +		hbc->set_alignment(BoxContainer::ALIGN_CENTER); +		hbc->add_constant_override("separation", 30 * EDSCALE); +		about->add_child(vbc); +		vbc->add_child(hbc); + +		TextureRect *logo = memnew(TextureRect); +		logo->set_texture(gui_base->get_icon("Logo", "EditorIcons")); +		hbc->add_child(logo); + +		Label *about_text = memnew(Label); +		about_text->set_text(VERSION_FULL_NAME + String::utf8("\n\u00A9 2007-2017 Juan Linietsky, Ariel Manzur.\n\u00A9 2014-2017 ") + +							 TTR("Godot Engine contributors") + "\n"); +		hbc->add_child(about_text); + +		TabContainer *tc = memnew(TabContainer); +		tc->set_custom_minimum_size(Size2(600, 240) * EDSCALE); +		tc->set_v_size_flags(Control::SIZE_EXPAND_FILL); +		vbc->add_child(tc); + +		ScrollContainer *dev_base = memnew(ScrollContainer); +		dev_base->set_name(TTR("Authors")); +		dev_base->set_v_size_flags(Control::SIZE_EXPAND); +		tc->add_child(dev_base); + +		VBoxContainer *dev_vbc = memnew(VBoxContainer); +		dev_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); +		dev_base->add_child(dev_vbc); + +		List<String> dev_sections; +		dev_sections.push_back(TTR("Project Founders")); +		dev_sections.push_back(TTR("Lead Developer")); +		dev_sections.push_back(TTR("Project Manager")); +		dev_sections.push_back(TTR("Developers")); + +		const char **dev_src[] = { dev_founders, dev_lead, dev_manager, dev_names }; + +		for (int i = 0; i < dev_sections.size(); i++) { + +			Label *lbl = memnew(Label); +			lbl->set_text(dev_sections[i]); +			dev_vbc->add_child(lbl); + +			ItemList *il = memnew(ItemList); +			il->set_max_columns(32); +			il->set_h_size_flags(Control::SIZE_EXPAND_FILL); +			il->set_custom_minimum_size(Size2(0, i == 3 ? DEV_NAMES_COUNT * 7.6 : 30) * EDSCALE); +			const char **dev_names_ptr = dev_src[i]; +			while (*dev_names_ptr) +				il->add_item(String::utf8(*dev_names_ptr++), NULL, false); +			dev_vbc->add_child(il); +			il->set_fixed_column_width(240 * EDSCALE); + +			HSeparator *hs = memnew(HSeparator); +			hs->set_modulate(Color(0, 0, 0, 0)); +			dev_vbc->add_child(hs);  		}  	} diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index e0a2ea624e..7948db3797 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -908,12 +908,20 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<ArrayMesh> &p_me  #ifndef NO_UP_AXIS_SWAP  				if (collada.state.up_axis == Vector3::AXIS_Z) { +					Vector3 bn = vertex.normal.cross(vertex.tangent.normal) * vertex.tangent.d; +  					SWAP(vertex.vertex.z, vertex.vertex.y);  					vertex.vertex.z = -vertex.vertex.z;  					SWAP(vertex.normal.z, vertex.normal.y);  					vertex.normal.z = -vertex.normal.z;  					SWAP(vertex.tangent.normal.z, vertex.tangent.normal.y);  					vertex.tangent.normal.z = -vertex.tangent.normal.z; +					SWAP(bn.z, bn.y); +					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/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a7a3242ad9..aedc96d20e 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1884,6 +1884,9 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {  	for (int i = 0; i < helps.size(); i++) {  		String path = helps[i]; +		if (path == "") { // invalid, skip +			continue; +		}  		_help_class_open(path);  	} diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index da2d22b900..e8fa3f78cc 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -658,7 +658,91 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {  				}  			}  		} break; - +		case TOOL_SCENE_EDITABLE_CHILDREN: { +			List<Node *> selection = editor_selection->get_selected_node_list(); +			if (List<Node *>::Element *e = selection.front()) { +				if (Node *node = e->get()) { +					bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node); +					editable = !editable; + +					EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, editable); +					menu->set_item_checked(18, editable); +					if (editable) { +						node->set_scene_instance_load_placeholder(false); +						menu->set_item_checked(19, false); +					} +					scene_tree->update_tree(); +				} +			} +		} break; +		case TOOL_SCENE_USE_PLACEHOLDER: { +			List<Node *> selection = editor_selection->get_selected_node_list(); +			if (List<Node *>::Element *e = selection.front()) { +				if (Node *node = e->get()) { +					bool placeholder = node->get_scene_instance_load_placeholder(); +					placeholder = !placeholder; +					if (placeholder) +						EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, false); + +					node->set_scene_instance_load_placeholder(placeholder); +					menu->set_item_checked(18, false); +					menu->set_item_checked(19, placeholder); +					scene_tree->update_tree(); +				} +			} +		} break; +		case TOOL_SCENE_CLEAR_INSTANCING: { +			List<Node *> selection = editor_selection->get_selected_node_list(); +			if (List<Node *>::Element *e = selection.front()) { +				if (Node *node = e->get()) { +					Node *root = EditorNode::get_singleton()->get_edited_scene(); +					UndoRedo *undo_redo = &editor_data->get_undo_redo(); +					if (!root) +						break; + +					ERR_FAIL_COND(node->get_filename() == String()); + +					undo_redo->create_action("Discard Instancing"); +					undo_redo->add_do_method(node, "set_filename", ""); +					undo_redo->add_undo_method(node, "set_filename", node->get_filename()); +					_node_replace_owner(node, node, root); +					undo_redo->add_do_method(scene_tree, "update_tree"); +					undo_redo->add_undo_method(scene_tree, "update_tree"); +					undo_redo->commit_action(); +				} +			} +		} break; +		case TOOL_SCENE_OPEN: { +			List<Node *> selection = editor_selection->get_selected_node_list(); +			if (List<Node *>::Element *e = selection.front()) { +				if (Node *node = e->get()) { +					scene_tree->emit_signal("open", node->get_filename()); +				} +			} +		} break; +		case TOOL_SCENE_CLEAR_INHERITANCE: { +			clear_inherit_confirm->popup_centered_minsize(); +		} break; +		case TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM: { +			List<Node *> selection = editor_selection->get_selected_node_list(); +			if (List<Node *>::Element *e = selection.front()) { +				if (Node *node = e->get()) { +					node->set_scene_inherited_state(Ref<SceneState>()); +					scene_tree->update_tree(); +					EditorNode::get_singleton()->get_property_editor()->update_tree(); +				} +			} +		} break; +		case TOOL_SCENE_OPEN_INHERITED: { +			List<Node *> selection = editor_selection->get_selected_node_list(); +			if (List<Node *>::Element *e = selection.front()) { +				if (Node *node = e->get()) { +					if (node && node->get_scene_inherited_state().is_valid()) { +						scene_tree->emit_signal("open", node->get_scene_inherited_state()->get_path()); +					} +				} +			} +		} break;  		default: {  			if (p_tool >= EDIT_SUBRESOURCE_BASE) { @@ -702,6 +786,29 @@ void SceneTreeDock::_notification(int p_what) {  			EditorNode::get_singleton()->get_editor_selection()->connect("selection_changed", this, "_selection_changed");  		} break; + +		case NOTIFICATION_ENTER_TREE: { +			clear_inherit_confirm->connect("confirmed", this, "_tool_selected", varray(TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM)); +		} break; + +		case NOTIFICATION_EXIT_TREE: { +			clear_inherit_confirm->disconnect("confirmed", this, "_tool_selected"); +		} break; +	} +} + +void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root) { + +	if (p_base != p_node) { +		if (p_node->get_owner() == p_base) { +			UndoRedo *undo_redo = &editor_data->get_undo_redo(); +			undo_redo->add_do_method(p_node, "set_owner", p_root); +			undo_redo->add_undo_method(p_node, "set_owner", p_base); +		} +	} + +	for (int i = 0; i < p_node->get_child_count(); i++) { +		_node_replace_owner(p_base, p_node->get_child(i), p_root);  	}  } @@ -1769,6 +1876,24 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {  		menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);  		menu->add_separator();  		menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH); +		bool is_external = (selection[0]->get_filename() != "") && (selection[0]->get_owner() != selection[0]); +		if (is_external) { +			bool is_inherited = selection[0]->get_scene_inherited_state() != NULL; +			menu->add_separator(); +			if (is_inherited) { +				menu->add_item(TTR("Clear Inheritance"), TOOL_SCENE_CLEAR_INHERITANCE); +				menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN_INHERITED); +			} else { +				bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(selection[0]); +				bool placeholder = selection[0]->get_scene_instance_load_placeholder(); +				menu->add_check_item(TTR("Editable Children"), TOOL_SCENE_EDITABLE_CHILDREN); +				menu->add_check_item(TTR("Load As Placeholder"), TOOL_SCENE_USE_PLACEHOLDER); +				menu->add_item(TTR("Discard Instancing"), TOOL_SCENE_CLEAR_INSTANCING); +				menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Open in Editor"), TOOL_SCENE_OPEN); +				menu->set_item_checked(18, editable); +				menu->set_item_checked(19, placeholder); +			} +		}  	}  	menu->add_separator();  	menu->add_icon_shortcut(get_icon("Remove", "EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); @@ -1978,6 +2103,11 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel  	first_enter = true;  	restore_script_editor_on_drag = false; +	clear_inherit_confirm = memnew(ConfirmationDialog); +	clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)")); +	clear_inherit_confirm->get_ok()->set_text(TTR("Clear!")); +	add_child(clear_inherit_confirm); +  	vbc->add_constant_override("separation", 4);  	set_process_input(true);  } diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 79e01e7571..5872c5a25d 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -70,7 +70,14 @@ class SceneTreeDock : public VBoxContainer {  		TOOL_MULTI_EDIT,  		TOOL_ERASE,  		TOOL_COPY_NODE_PATH, -		TOOL_BUTTON_MAX +		TOOL_BUTTON_MAX, +		TOOL_SCENE_EDITABLE_CHILDREN, +		TOOL_SCENE_USE_PLACEHOLDER, +		TOOL_SCENE_CLEAR_INSTANCING, +		TOOL_SCENE_OPEN, +		TOOL_SCENE_CLEAR_INHERITANCE, +		TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM, +		TOOL_SCENE_OPEN_INHERITED  	};  	enum { @@ -112,6 +119,7 @@ class SceneTreeDock : public VBoxContainer {  	TextureRect *filter_icon;  	PopupMenu *menu; +	ConfirmationDialog *clear_inherit_confirm;  	bool first_enter; @@ -127,6 +135,7 @@ class SceneTreeDock : public VBoxContainer {  	void _do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform);  	void _set_owners(Node *p_owner, const Array &p_nodes); +	void _node_replace_owner(Node *p_base, Node *p_node, Node *p_root);  	void _load_request(const String &p_path);  	void _script_open_request(const Ref<Script> &p_script); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index d4e5714c0d..d12d8b5528 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -44,110 +44,6 @@ Node *SceneTreeEditor::get_scene_node() {  	return get_tree()->get_edited_scene_root();  } -void SceneTreeEditor::_subscene_option(int p_idx) { - -	Object *obj = ObjectDB::get_instance(instance_node); -	if (!obj) -		return; -	Node *node = obj->cast_to<Node>(); -	if (!node) -		return; - -	switch (p_idx) { - -		case SCENE_MENU_EDITABLE_CHILDREN: { - -			bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(node); -			editable = !editable; - -			//node->set_instance_children_editable(editable); -			EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, editable); -			instance_menu->set_item_checked(0, editable); -			if (editable) { -				node->set_scene_instance_load_placeholder(false); -				instance_menu->set_item_checked(1, false); -			} - -			_update_tree(); - -		} break; -		case SCENE_MENU_USE_PLACEHOLDER: { - -			bool placeholder = node->get_scene_instance_load_placeholder(); -			placeholder = !placeholder; - -			//node->set_instance_children_editable(editable); -			if (placeholder) { -				EditorNode::get_singleton()->get_edited_scene()->set_editable_instance(node, false); -			} -			node->set_scene_instance_load_placeholder(placeholder); -			instance_menu->set_item_checked(0, false); -			instance_menu->set_item_checked(1, placeholder); - -			_update_tree(); - -		} break; -		case SCENE_MENU_OPEN: { - -			emit_signal("open", node->get_filename()); -		} break; -		case SCENE_MENU_CLEAR_INHERITANCE: { -			clear_inherit_confirm->popup_centered_minsize(); -		} break; -		case SCENE_MENU_CLEAR_INSTANCING: { - -			Node *root = EditorNode::get_singleton()->get_edited_scene(); -			if (!root) -				break; - -			ERR_FAIL_COND(node->get_filename() == String()); - -			undo_redo->create_action("Discard Instancing"); - -			undo_redo->add_do_method(node, "set_filename", ""); -			undo_redo->add_undo_method(node, "set_filename", node->get_filename()); - -			_node_replace_owner(node, node, root); - -			undo_redo->add_do_method(this, "update_tree"); -			undo_redo->add_undo_method(this, "update_tree"); - -			undo_redo->commit_action(); - -		} break; -		case SCENE_MENU_OPEN_INHERITED: { -			if (node && node->get_scene_inherited_state().is_valid()) { -				emit_signal("open", node->get_scene_inherited_state()->get_path()); -			} -		} break; -		case SCENE_MENU_CLEAR_INHERITANCE_CONFIRM: { -			if (node && node->get_scene_inherited_state().is_valid()) { -				node->set_scene_inherited_state(Ref<SceneState>()); -				update_tree(); -				EditorNode::get_singleton()->get_property_editor()->update_tree(); -			} - -		} break; -	} -} - -void SceneTreeEditor::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root) { - -	if (p_base != p_node) { - -		if (p_node->get_owner() == p_base) { - -			undo_redo->add_do_method(p_node, "set_owner", p_root); -			undo_redo->add_undo_method(p_node, "set_owner", p_base); -		} -	} - -	for (int i = 0; i < p_node->get_child_count(); i++) { - -		_node_replace_owner(p_base, p_node->get_child(i), p_root); -	} -} -  void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_id) {  	TreeItem *item = p_item->cast_to<TreeItem>(); @@ -159,38 +55,13 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i  	ERR_FAIL_COND(!n);  	if (p_id == BUTTON_SUBSCENE) { -		//open scene request -		Rect2 item_rect = tree->get_item_rect(item, 0); -		item_rect.position.y -= tree->get_scroll().y; -		item_rect.position += tree->get_global_position(); -  		if (n == get_scene_node()) { -			inheritance_menu->set_position(item_rect.position + Vector2(0, item_rect.size.y)); -			inheritance_menu->set_size(Vector2(item_rect.size.x, 0)); -			inheritance_menu->popup(); -			instance_node = n->get_instance_ID(); - -		} else { -			instance_menu->set_position(item_rect.position + Vector2(0, item_rect.size.y)); -			instance_menu->set_size(Vector2(item_rect.size.x, 0)); -			if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(n)) -				instance_menu->set_item_checked(0, true); -			else -				instance_menu->set_item_checked(0, false); - -			if (n->get_owner() == get_scene_node()) { -				instance_menu->set_item_checked(1, n->get_scene_instance_load_placeholder()); -				instance_menu->set_item_disabled(1, false); -			} else { - -				instance_menu->set_item_checked(1, false); -				instance_menu->set_item_disabled(1, true); +			if (n && n->get_scene_inherited_state().is_valid()) { +				emit_signal("open", n->get_scene_inherited_state()->get_path());  			} - -			instance_menu->popup(); -			instance_node = n->get_instance_ID(); +		} else { +			emit_signal("open", n->get_filename());  		} -		//emit_signal("open",n->get_filename());  	} else if (p_id == BUTTON_SCRIPT) {  		RefPtr script = n->get_script();  		if (!script.is_null()) @@ -472,7 +343,7 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) {  void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) {  	if (p_node->is_class("CanvasItem") || p_node->is_class("Spatial")) {  		Color color(1, 1, 1, 1); -		bool visible_on_screen = p_node->call("is_visible"); +		bool visible_on_screen = p_node->call("is_visible_in_tree");  		if (!visible_on_screen) {  			color = Color(0.6, 0.6, 0.6, 1);  		} @@ -633,10 +504,7 @@ void SceneTreeEditor::_notification(int p_what) {  		get_tree()->connect("node_removed", this, "_node_removed");  		get_tree()->connect("node_configuration_warning_changed", this, "_warning_changed"); -		instance_menu->set_item_icon(5, get_icon("Load", "EditorIcons"));  		tree->connect("item_collapsed", this, "_cell_collapsed"); -		inheritance_menu->set_item_icon(2, get_icon("Load", "EditorIcons")); -		clear_inherit_confirm->connect("confirmed", this, "_subscene_option", varray(SCENE_MENU_CLEAR_INHERITANCE_CONFIRM));  		EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed"); @@ -649,7 +517,6 @@ void SceneTreeEditor::_notification(int p_what) {  		get_tree()->disconnect("tree_changed", this, "_tree_changed");  		get_tree()->disconnect("node_removed", this, "_node_removed");  		tree->disconnect("item_collapsed", this, "_cell_collapsed"); -		clear_inherit_confirm->disconnect("confirmed", this, "_subscene_option");  		get_tree()->disconnect("node_configuration_warning_changed", this, "_warning_changed");  		EditorSettings::get_singleton()->disconnect("settings_changed", this, "_editor_settings_changed");  	} @@ -1059,7 +926,6 @@ void SceneTreeEditor::_bind_methods() {  	ClassDB::bind_method("_selection_changed", &SceneTreeEditor::_selection_changed);  	ClassDB::bind_method("_cell_button_pressed", &SceneTreeEditor::_cell_button_pressed);  	ClassDB::bind_method("_cell_collapsed", &SceneTreeEditor::_cell_collapsed); -	ClassDB::bind_method("_subscene_option", &SceneTreeEditor::_subscene_option);  	ClassDB::bind_method("_rmb_select", &SceneTreeEditor::_rmb_select);  	ClassDB::bind_method("_warning_changed", &SceneTreeEditor::_warning_changed); @@ -1145,29 +1011,6 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope  	updating_tree = false;  	blocked = 0; -	instance_menu = memnew(PopupMenu); -	instance_menu->add_check_item(TTR("Editable Children"), SCENE_MENU_EDITABLE_CHILDREN); -	instance_menu->add_check_item(TTR("Load As Placeholder"), SCENE_MENU_USE_PLACEHOLDER); -	instance_menu->add_separator(); -	instance_menu->add_item(TTR("Discard Instancing"), SCENE_MENU_CLEAR_INSTANCING); -	instance_menu->add_separator(); -	instance_menu->add_item(TTR("Open in Editor"), SCENE_MENU_OPEN); -	instance_menu->connect("id_pressed", this, "_subscene_option"); -	add_child(instance_menu); - -	inheritance_menu = memnew(PopupMenu); -	inheritance_menu->add_item(TTR("Clear Inheritance"), SCENE_MENU_CLEAR_INHERITANCE); -	inheritance_menu->add_separator(); -	inheritance_menu->add_item(TTR("Open in Editor"), SCENE_MENU_OPEN_INHERITED); -	inheritance_menu->connect("id_pressed", this, "_subscene_option"); - -	add_child(inheritance_menu); - -	clear_inherit_confirm = memnew(ConfirmationDialog); -	clear_inherit_confirm->set_text(TTR("Clear Inheritance? (No Undo!)")); -	clear_inherit_confirm->get_ok()->set_text(TTR("Clear!")); -	add_child(clear_inherit_confirm); -  	update_timer = memnew(Timer);  	update_timer->connect("timeout", this, "_update_tree");  	update_timer->set_one_shot(true); diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index ec7115afed..c6283af7b5 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -56,27 +56,14 @@ class SceneTreeEditor : public Control {  		BUTTON_GROUPS = 7,  	}; -	enum { -		SCENE_MENU_EDITABLE_CHILDREN, -		SCENE_MENU_USE_PLACEHOLDER, -		SCENE_MENU_OPEN, -		SCENE_MENU_CLEAR_INHERITANCE, -		SCENE_MENU_OPEN_INHERITED, -		SCENE_MENU_CLEAR_INHERITANCE_CONFIRM, -		SCENE_MENU_CLEAR_INSTANCING, -	}; -  	Tree *tree;  	Node *selected; -	PopupMenu *instance_menu; -	PopupMenu *inheritance_menu;  	ObjectID instance_node;  	String filter;  	AcceptDialog *error;  	AcceptDialog *warning; -	ConfirmationDialog *clear_inherit_confirm;  	int blocked; @@ -119,7 +106,6 @@ class SceneTreeEditor : public Control {  	void _node_script_changed(Node *p_node);  	void _node_visibility_changed(Node *p_node);  	void _update_visibility_color(Node *p_node, TreeItem *p_item); -	void _subscene_option(int p_idx);  	void _node_replace_owner(Node *p_base, Node *p_node, Node *p_root); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 066adde780..9d3493cb49 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -41,6 +41,7 @@  #include "platform/osx/logo.gen.h"  #include "string.h"  #include "version.h" +#include <sys/stat.h>  class EditorExportPlatformOSX : public EditorExportPlatform { @@ -52,6 +53,10 @@ class EditorExportPlatformOSX : public EditorExportPlatform {  	void _fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary);  	void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data); +#ifdef OSX_ENABLED +	Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path); +	Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name); +#endif  protected:  	virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features); @@ -61,7 +66,11 @@ public:  	virtual String get_name() const { return "Mac OSX"; }  	virtual Ref<Texture> get_logo() const { return logo; } +#ifdef OSX_ENABLED +	virtual String get_binary_extension() const { return "dmg"; } +#else  	virtual String get_binary_extension() const { return "zip"; } +#endif  	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; @@ -90,6 +99,11 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)  	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"), 0));  	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false)); + +#ifdef OSX_ENABLED +	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity"), "")); +	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements"), "")); +#endif  }  void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) { @@ -177,21 +191,62 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset  	}  } +#ifdef OSX_ENABLED +/** +	If we're running the OSX version of the Godot editor we'll: +	- export our application bundle to a temporary folder +	- attempt to code sign it +	- and then wrap it up in a DMG +**/ + +Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) { +	List<String> args; +	if (p_preset->get("codesign/entitlements") != "") { +		/* this should point to our entitlements.plist file that sandboxes our application, I don't know if this should also be placed in our app bundle */ +		args.push_back("-entitlements"); +		args.push_back(p_preset->get("codesign/entitlements")); +	} +	args.push_back("-s"); +	args.push_back(p_preset->get("codesign/identity")); +	args.push_back("-v"); /* provide some more feedback */ +	args.push_back(p_path); +	Error err = OS::get_singleton()->execute("/usr/bin/codesign", args, true); +	ERR_FAIL_COND_V(err, err); + +	return OK; +} + +Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name) { +	List<String> args; +	args.push_back("create"); +	args.push_back(p_dmg_path); +	args.push_back("-volname"); +	args.push_back(p_pkg_name); +	args.push_back("-fs"); +	args.push_back("HFS+"); +	args.push_back("-srcfolder"); +	args.push_back(p_app_path_name); +	Error err = OS::get_singleton()->execute("/usr/bin/hdiutil", args, true); +	ERR_FAIL_COND_V(err, err); + +	return OK; +} +  Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { -	String src_pkg; +	String src_pkg_name; -	EditorProgress ep("export", "Exporting for OSX", 104); +	EditorProgress ep("export", "Exporting for OSX", 3);  	if (p_debug) -		src_pkg = p_preset->get("custom_package/debug"); +		src_pkg_name = p_preset->get("custom_package/debug");  	else -		src_pkg = p_preset->get("custom_package/release"); +		src_pkg_name = p_preset->get("custom_package/release"); -	if (src_pkg == "") { +	if (src_pkg_name == "") {  		String err; -		src_pkg = find_export_template("osx.zip", &err); -		if (src_pkg == "") { +		src_pkg_name = find_export_template("osx.zip", &err); +		if (src_pkg_name == "") {  			EditorNode::add_io_error(err);  			return ERR_FILE_NOT_FOUND;  		} @@ -202,20 +257,15 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  	ep.step("Creating app", 0); -	unzFile pkg = unzOpen2(src_pkg.utf8().get_data(), &io); -	if (!pkg) { +	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); +		EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);  		return ERR_FILE_NOT_FOUND;  	} -	ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN); -	int ret = unzGoToFirstFile(pkg); - -	zlib_filefunc_def io2 = io; -	FileAccess *dst_f = NULL; -	io2.opaque = &dst_f; -	zipFile dpkg = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2); +	ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN); +	int ret = unzGoToFirstFile(src_pkg_zip);  	String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".";  	int bits_mode = p_preset->get("application/bits_mode"); @@ -230,14 +280,34 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  	else  		pkg_name = "Unnamed"; +	// We're on OSX so we can export to DMG, but first we create our application bundle +	String tmp_app_path_name = p_path.get_base_dir() + "/" + pkg_name + ".app"; +	print_line("Exporting to " + tmp_app_path_name); +	DirAccess *tmp_app_path = DirAccess::create_for_path(tmp_app_path_name); +	ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE) + +	///@TODO We should delete the existing application bundle especially if we attempt to code sign it, but what is a safe way to do this? Maybe call system function so it moves to trash? +	// tmp_app_path->erase_contents_recursive(); + +	// Create our folder structure or rely on unzip? +	print_line("Creating " + tmp_app_path_name + "/Contents/MacOS"); +	Error dir_err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS"); +	ERR_FAIL_COND_V(dir_err, ERR_CANT_CREATE) +	print_line("Creating " + tmp_app_path_name + "/Contents/Resources"); +	dir_err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources"); +	ERR_FAIL_COND_V(dir_err, 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(pkg, &info, fname, 16384, NULL, 0, NULL, 0); +		ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, NULL, 0, NULL, 0);  		String file = fname; @@ -246,9 +316,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  		data.resize(info.uncompressed_size);  		//read -		unzOpenCurrentFile(pkg); -		unzReadCurrentFile(pkg, data.ptr(), data.size()); -		unzCloseCurrentFile(pkg); +		unzOpenCurrentFile(src_pkg_zip); +		unzReadCurrentFile(src_pkg_zip, data.ptr(), data.size()); +		unzCloseCurrentFile(src_pkg_zip);  		//write @@ -261,10 +331,11 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  		if (file.begins_with("Contents/MacOS/godot_")) {  			if (file != "Contents/MacOS/" + binary_to_use) { -				ret = unzGoToNextFile(pkg); +				ret = unzGoToNextFile(src_pkg_zip);  				continue; //ignore!  			}  			found_binary = true; +			is_execute = true;  			file = "Contents/MacOS/" + pkg_name;  		} @@ -288,11 +359,206 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  			//bleh?  		} -		file = pkg_name + ".app/" + file; +		if (data.size() > 0) { +			print_line("ADDING: " + file + " size: " + itos(data.size())); +			total_size += data.size(); + +			/* write it into our application bundle */ +			file = tmp_app_path_name + "/" + file; + +			/* write the file, need to add chmod */ +			FileAccess *f = FileAccess::open(file, FileAccess::WRITE); +			ERR_FAIL_COND_V(!f, 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); +			} else { +				// seems to already be set correctly +				// chmod(file.utf8().get_data(), 0644); +			} +		} + +		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 = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck"; +	Error err = save_pack(p_preset, pack_path); +	//	chmod(pack_path.utf8().get_data(), 0644); + +	if (err) { +		return err; +	} + +	/* see if we can code sign our new package */ +	if (p_preset->get("codesign/identity") != "") { +		ep.step("Code signing bundle", 2); + +		/* the order in which we code sign is important, this is a bit of a shame or we could do this in our loop that extracts the files from our ZIP */ + +		// start with our application +		err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name); +		ERR_FAIL_COND_V(err, err); + +		///@TODO we should check the contents of /Contents/Frameworks for frameworks to sign + +		// we should probably loop through all resources and sign them? +		err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Resources/icon.icns"); +		ERR_FAIL_COND_V(err, err); +		err = _code_sign(p_preset, pack_path); +		ERR_FAIL_COND_V(err, err); +		err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Info.plist"); +		ERR_FAIL_COND_V(err, err); +	} + +	/* and finally create a DMG */ +	ep.step("Making DMG", 3); +	err = _create_dmg(p_path, pkg_name, tmp_app_path_name); +	ERR_FAIL_COND_V(err, err); + +	return OK; +} + +#else + +/** +	When exporting for OSX from any other platform we don't have access to code signing or creating DMGs so we'll wrap the bundle into a zip file. + +	Should probably find a nicer way to have just one export method instead of duplicating the method like this but I would the code got very  +	messy with switches inside of it. +**/ +Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { + +	String src_pkg_name; + +	EditorProgress ep("export", "Exporting for OSX", 104); + +	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("osx.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_osx_" + 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 ? "64" : "32"); + +	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"; + +	/* Open our destination zip file */ +	zlib_filefunc_def io2 = io; +	FileAccess *dst_f = NULL; +	io2.opaque = &dst_f; +	zipFile dst_pkg_zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, NULL, &io2); + +	bool found_binary = false; + +	while (ret == UNZ_OK) { + +		//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("osx_template.app/", ""); + +		if (file == "Contents/Info.plist") { +			print_line("parse plist"); +			_fix_plist(p_preset, data, pkg_name); +		} + +		if (file.begins_with("Contents/MacOS/godot_")) { +			if (file != "Contents/MacOS/" + binary_to_use) { +				ret = unzGoToNextFile(src_pkg_zip); +				continue; //ignore! +			} +			found_binary = true; +			file = "Contents/MacOS/" + pkg_name; +		} + +		if (file == "Contents/Resources/icon.icns") { +			//see if there is an icon +			String iconpath; +			if (p_preset->get("application/icon") != "") +				iconpath = p_preset->get("application/icon"); +			else +				iconpath = GlobalConfig::get_singleton()->get("application/icon"); +			print_line("icon? " + iconpath); +			if (iconpath != "") { +				Ref<Image> icon; +				icon.instance(); +				icon->load(iconpath); +				if (!icon->empty()) { +					print_line("loaded?"); +					_make_icon(icon, data); +				} +			} +			//bleh? +		}  		if (data.size() > 0) {  			print_line("ADDING: " + file + " size: " + itos(data.size())); +			/* add it to our zip file */ +			file = pkg_name + ".app/" + file; +  			zip_fileinfo fi;  			fi.tmz_date.tm_hour = info.tmu_date.tm_hour;  			fi.tmz_date.tm_min = info.tmu_date.tm_min; @@ -304,7 +570,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  			fi.internal_fa = info.internal_fa;  			fi.external_fa = info.external_fa; -			int err = zipOpenNewFileInZip(dpkg, +			int err = zipOpenNewFileInZip(dst_pkg_zip,  					file.utf8().get_data(),  					&fi,  					NULL, @@ -316,37 +582,37 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  					Z_DEFAULT_COMPRESSION);  			print_line("OPEN ERR: " + itos(err)); -			err = zipWriteInFileInZip(dpkg, data.ptr(), data.size()); +			err = zipWriteInFileInZip(dst_pkg_zip, data.ptr(), data.size());  			print_line("WRITE ERR: " + itos(err)); -			zipCloseFileInZip(dpkg); +			zipCloseFileInZip(dst_pkg_zip);  		} -		ret = unzGoToNextFile(pkg); +		ret = unzGoToNextFile(src_pkg_zip);  	}  	if (!found_binary) {  		ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive."); -		zipClose(dpkg, NULL); -		unzClose(pkg); +		zipClose(dst_pkg_zip, NULL); +		unzClose(src_pkg_zip);  		return ERR_FILE_NOT_FOUND;  	}  	ep.step("Making PKG", 1); -	String pack_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/data.pck"; +	String pack_path = EditorSettings::get_singleton()->get_settings_path() + "/tmp/" + pkg_name + ".pck";  	Error err = save_pack(p_preset, pack_path);  	if (err) { -		zipClose(dpkg, NULL); -		unzClose(pkg); +		zipClose(dst_pkg_zip, NULL); +		unzClose(src_pkg_zip);  		return err;  	}  	{  		//write datapack -		zipOpenNewFileInZip(dpkg, -				(pkg_name + ".app/Contents/Resources/data.pck").utf8().get_data(), +		zipOpenNewFileInZip(dst_pkg_zip, +				(pkg_name + ".app/Contents/Resources/" + pkg_name + ".pck").utf8().get_data(),  				NULL,  				NULL,  				0, @@ -366,17 +632,18 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  			int r = pf->get_buffer(buf, BSIZE);  			if (r <= 0)  				break; -			zipWriteInFileInZip(dpkg, buf, r); +			zipWriteInFileInZip(dst_pkg_zip, buf, r);  		} -		zipCloseFileInZip(dpkg); +		zipCloseFileInZip(dst_pkg_zip);  		memdelete(pf);  	} -	zipClose(dpkg, NULL); -	unzClose(pkg); +	zipClose(dst_pkg_zip, NULL); +	unzClose(src_pkg_zip);  	return OK;  } +#endif  bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 6fe1dd73fe..bd6ab99801 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -319,7 +319,7 @@ void Node2D::set_global_scale(const Size2 &p_scale) {  	CanvasItem *pi = get_parent_item();  	if (pi) {  		const Size2 parent_global_scale = pi->get_global_transform().get_scale(); -		set_scale(p_scale - parent_global_scale); +		set_scale(p_scale / parent_global_scale);  	} else {  		set_scale(p_scale);  	} diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index a0d9c26430..14886f4b7a 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -32,6 +32,7 @@  #include "body_shape.h"  #include "core_string_names.h"  #include "physics_body.h" +#include "scene/resources/material.h"  #include "scene/scene_string_names.h"  #include "skeleton.h"  bool MeshInstance::_set(const StringName &p_name, const Variant &p_value) { @@ -274,6 +275,80 @@ void MeshInstance::_mesh_changed() {  	materials.resize(mesh->get_surface_count());  } +void MeshInstance::create_debug_tagents() { + +	Vector<Vector3> lines; +	Vector<Color> colors; + +	Ref<Mesh> mesh = get_mesh(); +	if (!mesh.is_valid()) +		return; + +	for (int i = 0; i < mesh->get_surface_count(); i++) { +		Array arrays = mesh->surface_get_arrays(i); +		Vector<Vector3> verts = arrays[Mesh::ARRAY_VERTEX]; +		Vector<Vector3> norms = arrays[Mesh::ARRAY_NORMAL]; +		if (norms.size() == 0) +			continue; +		Vector<float> tangents = arrays[Mesh::ARRAY_TANGENT]; +		if (tangents.size() == 0) +			continue; + +		for (int j = 0; j < verts.size(); j++) { +			Vector3 v = verts[j]; +			Vector3 n = norms[j]; +			Vector3 t = Vector3(tangents[j * 4 + 0], tangents[j * 4 + 1], tangents[j * 4 + 2]); +			Vector3 b = (n.cross(t)).normalized() * tangents[j * 4 + 3]; + +			lines.push_back(v); //normal +			colors.push_back(Color(0, 0, 1)); //color +			lines.push_back(v + n * 0.04); //normal +			colors.push_back(Color(0, 0, 1)); //color + +			lines.push_back(v); //tangent +			colors.push_back(Color(1, 0, 0)); //color +			lines.push_back(v + t * 0.04); //tangent +			colors.push_back(Color(1, 0, 0)); //color + +			lines.push_back(v); //binormal +			colors.push_back(Color(0, 1, 0)); //color +			lines.push_back(v + b * 0.04); //binormal +			colors.push_back(Color(0, 1, 0)); //color +		} +	} + +	if (lines.size()) { + +		Ref<SpatialMaterial> sm; +		sm.instance(); + +		sm->set_flag(SpatialMaterial::FLAG_UNSHADED, true); +		sm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); +		sm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + +		Ref<ArrayMesh> am; +		am.instance(); +		Array a; +		a.resize(Mesh::ARRAY_MAX); +		a[Mesh::ARRAY_VERTEX] = lines; +		a[Mesh::ARRAY_COLOR] = colors; + +		am->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); +		am->surface_set_material(0, sm); + +		MeshInstance *mi = memnew(MeshInstance); +		mi->set_mesh(am); +		mi->set_name("DebugTangents"); +		add_child(mi); +		if (get_parent()) { +			if (get_parent() == get_tree()->get_edited_scene_root()) +				mi->set_owner(get_parent()); +			else +				mi->set_owner(get_parent()->get_owner()); +		} +	} +} +  void MeshInstance::_bind_methods() {  	ClassDB::bind_method(D_METHOD("set_mesh", "mesh:Mesh"), &MeshInstance::set_mesh); @@ -290,6 +365,9 @@ void MeshInstance::_bind_methods() {  	ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);  	ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed); +	ClassDB::bind_method(D_METHOD("create_debug_tagents"), &MeshInstance::create_debug_tagents); +	ClassDB::set_method_flags("MeshInstance", "create_debug_tagents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); +  	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");  	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton_path", "get_skeleton_path");  } diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index c11c52b76d..be328084af 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -83,6 +83,8 @@ public:  	Node *create_convex_collision_node();  	void create_convex_collision(); +	void create_debug_tagents(); +  	virtual Rect3 get_aabb() const;  	virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 3debbf02c3..20c2cc1eb5 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -541,10 +541,7 @@ void Spatial::show() {  	if (!is_inside_tree())  		return; -	if (!data.parent || is_visible_in_tree()) { - -		_propagate_visibility_changed(); -	} +	_propagate_visibility_changed();  }  void Spatial::hide() { @@ -552,14 +549,14 @@ void Spatial::hide() {  	if (!data.visible)  		return; -	bool was_visible = is_visible_in_tree();  	data.visible = false; -	if (!data.parent || was_visible) { +	if (!is_inside_tree()) +		return; -		_propagate_visibility_changed(); -	} +	_propagate_visibility_changed();  } +  bool Spatial::is_visible_in_tree() const {  	const Spatial *s = this; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 0c65c44392..61e563143c 100755 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -37,7 +37,6 @@  #include "viewport.h"  VARIANT_ENUM_CAST(Node::PauseMode); -VARIANT_ENUM_CAST(Node::NetworkMode);  VARIANT_ENUM_CAST(Node::RPCMode);  void Node::_notification(int p_notification) { @@ -77,16 +76,6 @@ void Node::_notification(int p_notification) {  				data.pause_owner = this;  			} -			if (data.network_mode == NETWORK_MODE_INHERIT) { - -				if (data.parent) -					data.network_owner = data.parent->data.network_owner; -				else -					data.network_owner = NULL; -			} else { -				data.network_owner = this; -			} -  			if (data.input)  				add_to_group("_vp_input" + itos(get_viewport()->get_instance_ID()));  			if (data.unhandled_input) @@ -108,7 +97,6 @@ void Node::_notification(int p_notification) {  				remove_from_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_ID()));  			data.pause_owner = NULL; -			data.network_owner = NULL;  			if (data.path_cache) {  				memdelete(data.path_cache);  				data.path_cache = NULL; @@ -472,69 +460,28 @@ void Node::_propagate_pause_owner(Node *p_owner) {  	}  } -void Node::set_network_mode(NetworkMode p_mode) { +void Node::set_network_master(int p_peer_id, bool p_recursive) { -	if (data.network_mode == p_mode) -		return; +	data.network_master = p_peer_id; -	bool prev_inherits = data.network_mode == NETWORK_MODE_INHERIT; -	data.network_mode = p_mode; -	if (!is_inside_tree()) -		return; //pointless -	if ((data.network_mode == NETWORK_MODE_INHERIT) == prev_inherits) -		return; ///nothing changed - -	Node *owner = NULL; - -	if (data.network_mode == NETWORK_MODE_INHERIT) { +	if (p_recursive) { +		for (int i = 0; i < data.children.size(); i++) { -		if (data.parent) -			owner = data.parent->data.network_owner; -	} else { -		owner = this; +			data.children[i]->set_network_master(p_peer_id, true); +		}  	} - -	_propagate_network_owner(owner);  } -Node::NetworkMode Node::get_network_mode() const { +int Node::get_network_master() const { -	return data.network_mode; +	return data.network_master;  }  bool Node::is_network_master() const {  	ERR_FAIL_COND_V(!is_inside_tree(), false); -	switch (data.network_mode) { -		case NETWORK_MODE_INHERIT: { - -			if (data.network_owner) -				return data.network_owner->is_network_master(); -			else -				return get_tree()->is_network_server(); -		} break; -		case NETWORK_MODE_MASTER: { - -			return true; -		} break; -		case NETWORK_MODE_SLAVE: { -			return false; -		} break; -	} - -	return false; -} - -void Node::_propagate_network_owner(Node *p_owner) { - -	if (data.network_mode != NETWORK_MODE_INHERIT) -		return; -	data.network_owner = p_owner; -	for (int i = 0; i < data.children.size(); i++) { - -		data.children[i]->_propagate_network_owner(p_owner); -	} +	return get_tree()->get_network_unique_id() == data.network_master;  }  /***** RPC CONFIG ********/ @@ -962,7 +909,7 @@ void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const  //////////// end of rpc -bool Node::can_call_rpc(const StringName &p_method) const { +bool Node::can_call_rpc(const StringName &p_method, int p_from) const {  	const Map<StringName, RPCMode>::Element *E = data.rpc_methods.find(p_method);  	if (E) { @@ -982,7 +929,7 @@ bool Node::can_call_rpc(const StringName &p_method) const {  				return is_network_master();  			} break;  			case RPC_MODE_SLAVE: { -				return !is_network_master(); +				return !is_network_master() && p_from == get_network_master();  			} break;  		}  	} @@ -1006,16 +953,16 @@ bool Node::can_call_rpc(const StringName &p_method) const {  				return is_network_master();  			} break;  			case ScriptInstance::RPC_MODE_SLAVE: { -				return !is_network_master(); +				return !is_network_master() && p_from == get_network_master();  			} break;  		}  	} -	ERR_PRINTS("RPC on unauthorized method attempted: " + String(p_method) + " on base: " + String(Variant(this))); +	ERR_PRINTS("RPC from " + itos(p_from) + " on unauthorized method attempted: " + String(p_method) + " on base: " + String(Variant(this)));  	return false;  } -bool Node::can_call_rset(const StringName &p_property) const { +bool Node::can_call_rset(const StringName &p_property, int p_from) const {  	const Map<StringName, RPCMode>::Element *E = data.rpc_properties.find(p_property);  	if (E) { @@ -1035,7 +982,7 @@ bool Node::can_call_rset(const StringName &p_property) const {  				return is_network_master();  			} break;  			case RPC_MODE_SLAVE: { -				return !is_network_master(); +				return !is_network_master() && p_from == get_network_master();  			} break;  		}  	} @@ -1059,12 +1006,12 @@ bool Node::can_call_rset(const StringName &p_property) const {  				return is_network_master();  			} break;  			case ScriptInstance::RPC_MODE_SLAVE: { -				return !is_network_master(); +				return !is_network_master() && p_from == get_network_master();  			} break;  		}  	} -	ERR_PRINTS("RSET on unauthorized property attempted: " + String(p_property) + " on base: " + String(Variant(this))); +	ERR_PRINTS("RSET from " + itos(p_from) + " on unauthorized property attempted: " + String(p_property) + " on base: " + String(Variant(this)));  	return false;  } @@ -2845,8 +2792,8 @@ void Node::_bind_methods() {  	ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready); -	ClassDB::bind_method(D_METHOD("set_network_mode", "mode"), &Node::set_network_mode); -	ClassDB::bind_method(D_METHOD("get_network_mode"), &Node::get_network_mode); +	ClassDB::bind_method(D_METHOD("set_network_master", "id", "recursive"), &Node::set_network_master, DEFVAL(true)); +	ClassDB::bind_method(D_METHOD("get_network_master"), &Node::get_network_master);  	ClassDB::bind_method(D_METHOD("is_network_master"), &Node::is_network_master); @@ -2902,10 +2849,6 @@ void Node::_bind_methods() {  	BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);  	BIND_CONSTANT(NOTIFICATION_INTERNAL_FIXED_PROCESS); -	BIND_CONSTANT(NETWORK_MODE_INHERIT); -	BIND_CONSTANT(NETWORK_MODE_MASTER); -	BIND_CONSTANT(NETWORK_MODE_SLAVE); -  	BIND_CONSTANT(RPC_MODE_DISABLED);  	BIND_CONSTANT(RPC_MODE_REMOTE);  	BIND_CONSTANT(RPC_MODE_SYNC); @@ -2977,8 +2920,7 @@ Node::Node() {  	data.unhandled_key_input = false;  	data.pause_mode = PAUSE_MODE_INHERIT;  	data.pause_owner = NULL; -	data.network_mode = NETWORK_MODE_INHERIT; -	data.network_owner = NULL; +	data.network_master = 1; //server by default  	data.path_cache = NULL;  	data.parent_owned = false;  	data.in_constructor = true; diff --git a/scene/main/node.h b/scene/main/node.h index ffd2b7ce5f..7baa65c022 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -61,13 +61,6 @@ public:  		DUPLICATE_USE_INSTANCING = 8  	}; -	enum NetworkMode { - -		NETWORK_MODE_INHERIT, -		NETWORK_MODE_MASTER, -		NETWORK_MODE_SLAVE -	}; -  	enum RPCMode {  		RPC_MODE_DISABLED, //no rpc for this method, calls to this will be blocked (default) @@ -122,8 +115,7 @@ private:  		PauseMode pause_mode;  		Node *pause_owner; -		NetworkMode network_mode; -		Node *network_owner; +		int network_master;  		Map<StringName, RPCMode> rpc_methods;  		Map<StringName, RPCMode> rpc_properties; @@ -173,7 +165,6 @@ private:  	void _propagate_validate_owner();  	void _print_stray_nodes();  	void _propagate_pause_owner(Node *p_owner); -	void _propagate_network_owner(Node *p_owner);  	Array _get_node_and_resource(const NodePath &p_path);  	void _duplicate_signals(const Node *p_original, Node *p_copy) const; @@ -393,8 +384,8 @@ public:  	bool is_displayed_folded() const;  	/* NETWORK */ -	void set_network_mode(NetworkMode p_mode); -	NetworkMode get_network_mode() const; +	void set_network_master(int p_peer_id, bool p_recursive = true); +	int get_network_master() const;  	bool is_network_master() const;  	void rpc_config(const StringName &p_method, RPCMode p_mode); // config a local method for RPC @@ -414,8 +405,8 @@ public:  	void rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value); -	bool can_call_rpc(const StringName &p_method) const; -	bool can_call_rset(const StringName &p_property) const; +	bool can_call_rpc(const StringName &p_method, int p_from) const; +	bool can_call_rset(const StringName &p_property, int p_from) const;  	Node();  	~Node(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 479abccda6..1e5735de97 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1763,6 +1763,16 @@ int SceneTree::get_network_unique_id() const {  	return network_peer->get_unique_id();  } +Vector<int> SceneTree::get_network_connected_peers() const { +	ERR_FAIL_COND_V(!network_peer.is_valid(), Vector<int>()); + +	Vector<int> ret; +	for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { +		ret.push_back(E->get()); +	} + +	return ret; +}  void SceneTree::set_refuse_new_network_connections(bool p_refuse) {  	ERR_FAIL_COND(!network_peer.is_valid());  	network_peer->set_refuse_new_connections(p_refuse); @@ -1973,6 +1983,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int  			Node *node = NULL;  			if (target & 0x80000000) { +				//use full path (not cached yet)  				int ofs = target & 0x7FFFFFFF;  				ERR_FAIL_COND(ofs >= p_packet_len); @@ -1988,7 +1999,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int  					ERR_FAIL_COND(node == NULL);  				}  			} else { - +				//use cached path  				int id = target;  				Map<int, PathGetCache>::Element *E = path_get_cache.find(p_from); @@ -2023,7 +2034,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int  			if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { -				if (!node->can_call_rpc(name)) +				if (!node->can_call_rpc(name, p_from))  					return;  				int ofs = len_end + 1; @@ -2060,7 +2071,7 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int  			} else { -				if (!node->can_call_rset(name)) +				if (!node->can_call_rset(name, p_from))  					return;  				int ofs = len_end + 1; @@ -2236,6 +2247,7 @@ void SceneTree::_bind_methods() {  	ClassDB::bind_method(D_METHOD("set_network_peer", "peer:NetworkedMultiplayerPeer"), &SceneTree::set_network_peer);  	ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);  	ClassDB::bind_method(D_METHOD("has_network_peer"), &SceneTree::has_network_peer); +	ClassDB::bind_method(D_METHOD("get_network_connected_peers"), &SceneTree::get_network_connected_peers);  	ClassDB::bind_method(D_METHOD("get_network_unique_id"), &SceneTree::get_network_unique_id);  	ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections);  	ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 2ea79bf945..76a4becdbc 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -451,6 +451,7 @@ public:  	bool is_network_server() const;  	bool has_network_peer() const;  	int get_network_unique_id() const; +	Vector<int> get_network_connected_peers() const;  	void set_refuse_new_network_connections(bool p_refuse);  	bool is_refusing_new_network_connections() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 3934467855..6209f99d9d 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -452,7 +452,7 @@ void SpatialMaterial::_update_shader() {  	if (features[FEATURE_DEPTH_MAPPING]) {  		code += "\t{\n"; -		code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT,BINORMAL,NORMAL));\n"; +		code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT,-BINORMAL,NORMAL));\n"; //binormal is negative due to mikktpsace  		if (deep_parallax) {  			code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; @@ -1265,7 +1265,7 @@ void SpatialMaterial::_bind_methods() {  	ADD_GROUP("Anisotropy", "anisotropy_");  	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anisotropy_enabled"), "set_feature", "get_feature", FEATURE_ANISOTROPY); -	ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy", "get_anisotropy"); +	ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy");  	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_FLOWMAP);  	ADD_GROUP("Ambient Occlusion", "ao_"); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 6e41cef4a0..81cfd0e5f0 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -171,7 +171,9 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {  	float onethird = 1.0 / 3.0;  	float twothirds = 2.0 / 3.0; -	set_aabb(Rect3(Vector3(-radius, (mid_height * -0.5) - radius, -radius), Vector3(radius * 2.0, mid_height + (2.0 * radius), radius * 2.0))); +	// note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom + +	set_aabb(Rect3(Vector3(-radius, -radius, (mid_height * -0.5) - radius), Vector3(radius * 2.0, radius * 2.0, mid_height + (2.0 * radius))));  	PoolVector<Vector3> points;  	PoolVector<Vector3> normals; @@ -195,19 +197,19 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {  		v /= (rings + 1);  		w = sin(0.5 * Math_PI * v); -		y = radius * cos(0.5 * Math_PI * v); +		z = radius * cos(0.5 * Math_PI * v);  		for (i = 0; i <= radial_segments; i++) {  			u = i;  			u /= radial_segments;  			x = sin(u * (Math_PI * 2.0)); -			z = cos(u * (Math_PI * 2.0)); +			y = -cos(u * (Math_PI * 2.0)); -			Vector3 p = Vector3(x * radius * w, y, z * radius * w); -			points.push_back(p + Vector3(0.0, 0.5 * mid_height, 0.0)); +			Vector3 p = Vector3(x * radius * w, y * radius * w, z); +			points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));  			normals.push_back(p.normalized()); -			ADD_TANGENT(-z, 0.0, x, -1.0) +			ADD_TANGENT(y, -x, 0.0, -1.0)  			uvs.push_back(Vector2(u, v * onethird));  			point++; @@ -233,20 +235,20 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {  		v = j;  		v /= (rings + 1); -		y = mid_height * v; -		y = (mid_height * 0.5) - y; +		z = mid_height * v; +		z = (mid_height * 0.5) - z;  		for (i = 0; i <= radial_segments; i++) {  			u = i;  			u /= radial_segments;  			x = sin(u * (Math_PI * 2.0)); -			z = cos(u * (Math_PI * 2.0)); +			y = -cos(u * (Math_PI * 2.0)); -			Vector3 p = Vector3(x * radius, y, z * radius); +			Vector3 p = Vector3(x * radius, y * radius, z);  			points.push_back(p); -			normals.push_back(Vector3(x, 0.0, z)); -			ADD_TANGENT(-z, 0.0, x, -1.0) +			normals.push_back(Vector3(x, y, 0.0)); +			ADD_TANGENT(y, -x, 0.0, -1.0)  			uvs.push_back(Vector2(u, onethird + (v * onethird)));  			point++; @@ -275,19 +277,19 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) {  		v /= (rings + 1);  		v += 1.0;  		w = sin(0.5 * Math_PI * v); -		y = radius * cos(0.5 * Math_PI * v); +		z = radius * cos(0.5 * Math_PI * v);  		for (i = 0; i <= radial_segments; i++) {  			float u = i;  			u /= radial_segments;  			x = sin(u * (Math_PI * 2.0)); -			z = cos(u * (Math_PI * 2.0)); +			y = -cos(u * (Math_PI * 2.0)); -			Vector3 p = Vector3(x * radius * w, y, z * radius * w); -			points.push_back(p + Vector3(0.0, -0.5 * mid_height, 0.0)); +			Vector3 p = Vector3(x * radius * w, y * radius * w, z); +			points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));  			normals.push_back(p.normalized()); -			ADD_TANGENT(-z, 0.0, x, -1.0) +			ADD_TANGENT(y, -x, 0.0, -1.0)  			uvs.push_back(Vector2(u, twothirds + ((v - 1.0) * onethird)));  			point++; diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index eb0848ff50..c833f4eabd 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1262,9 +1262,9 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format, PoolVector<uint8_  					for (int j = 0; j < p_vertex_len; j++) { -						const uint8_t *v = (const uint8_t *)&r[j * total_elem_size + offsets[i]]; +						const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]];  						for (int k = 0; k < 4; k++) { -							w[j * 4 + k] = float(v[k] / 255.0) * 2.0 - 1.0; +							w[j * 4 + k] = float(v[k] / 127.0);  						}  					}  				} else {  |