1 #include "material_editor_plugin.h"
2 #include "scene/main/viewport.h"
3 
_input_event(InputEvent p_event)4 void MaterialEditor::_input_event(InputEvent p_event) {
5 }
6 
_notification(int p_what)7 void MaterialEditor::_notification(int p_what) {
8 
9 	if (p_what == NOTIFICATION_FIXED_PROCESS) {
10 	}
11 
12 	if (p_what == NOTIFICATION_READY) {
13 
14 		//get_scene()->connect("node_removed",this,"_node_removed");
15 
16 		if (first_enter) {
17 			//it's in propertyeditor so.. could be moved around
18 
19 			light_1_switch->set_normal_texture(get_icon("MaterialPreviewLight1", "EditorIcons"));
20 			light_1_switch->set_pressed_texture(get_icon("MaterialPreviewLight1Off", "EditorIcons"));
21 			light_2_switch->set_normal_texture(get_icon("MaterialPreviewLight2", "EditorIcons"));
22 			light_2_switch->set_pressed_texture(get_icon("MaterialPreviewLight2Off", "EditorIcons"));
23 
24 			sphere_switch->set_normal_texture(get_icon("MaterialPreviewSphereOff", "EditorIcons"));
25 			sphere_switch->set_pressed_texture(get_icon("MaterialPreviewSphere", "EditorIcons"));
26 			box_switch->set_normal_texture(get_icon("MaterialPreviewCubeOff", "EditorIcons"));
27 			box_switch->set_pressed_texture(get_icon("MaterialPreviewCube", "EditorIcons"));
28 
29 			first_enter = false;
30 		}
31 	}
32 
33 	if (p_what == NOTIFICATION_DRAW) {
34 
35 		Ref<Texture> checkerboard = get_icon("Checkerboard", "EditorIcons");
36 		Size2 size = get_size();
37 
38 		draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
39 	}
40 }
41 
edit(Ref<Material> p_material)42 void MaterialEditor::edit(Ref<Material> p_material) {
43 
44 	material = p_material;
45 
46 	if (!material.is_null()) {
47 		sphere_mesh->surface_set_material(0, material);
48 		box_mesh->surface_set_material(0, material);
49 	} else {
50 
51 		hide();
52 	}
53 }
54 
_button_pressed(Node * p_button)55 void MaterialEditor::_button_pressed(Node *p_button) {
56 
57 	if (p_button == light_1_switch) {
58 		light1->set_enabled(!light_1_switch->is_pressed());
59 	}
60 
61 	if (p_button == light_2_switch) {
62 		light2->set_enabled(!light_2_switch->is_pressed());
63 	}
64 
65 	if (p_button == box_switch) {
66 		box_instance->show();
67 		sphere_instance->hide();
68 		box_switch->set_pressed(true);
69 		sphere_switch->set_pressed(false);
70 	}
71 
72 	if (p_button == sphere_switch) {
73 		box_instance->hide();
74 		sphere_instance->show();
75 		box_switch->set_pressed(false);
76 		sphere_switch->set_pressed(true);
77 	}
78 }
79 
_bind_methods()80 void MaterialEditor::_bind_methods() {
81 
82 	ObjectTypeDB::bind_method(_MD("_input_event"), &MaterialEditor::_input_event);
83 	ObjectTypeDB::bind_method(_MD("_button_pressed"), &MaterialEditor::_button_pressed);
84 }
85 
MaterialEditor()86 MaterialEditor::MaterialEditor() {
87 
88 	viewport = memnew(Viewport);
89 	Ref<World> world;
90 	world.instance();
91 	viewport->set_world(world); //use own world
92 	add_child(viewport);
93 	viewport->set_disable_input(true);
94 
95 	camera = memnew(Camera);
96 	camera->set_transform(Transform(Matrix3(), Vector3(0, 0, 3)));
97 	camera->set_perspective(45, 0.1, 10);
98 	viewport->add_child(camera);
99 
100 	light1 = memnew(DirectionalLight);
101 	light1->set_transform(Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
102 	viewport->add_child(light1);
103 
104 	light2 = memnew(DirectionalLight);
105 	light2->set_transform(Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
106 	light2->set_color(Light::COLOR_DIFFUSE, Color(0.7, 0.7, 0.7));
107 	light2->set_color(Light::COLOR_SPECULAR, Color(0.7, 0.7, 0.7));
108 	viewport->add_child(light2);
109 
110 	sphere_instance = memnew(MeshInstance);
111 	viewport->add_child(sphere_instance);
112 
113 	box_instance = memnew(MeshInstance);
114 	viewport->add_child(box_instance);
115 
116 	Transform box_xform;
117 	box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg2rad(-25));
118 	box_xform.basis = box_xform.basis * Matrix3().rotated(Vector3(0, 1, 0), Math::deg2rad(-25));
119 	box_xform.basis.scale(Vector3(0.8, 0.8, 0.8));
120 	box_instance->set_transform(box_xform);
121 
122 	{
123 
124 		sphere_mesh.instance();
125 
126 		int lats = 32;
127 		int lons = 32;
128 		float radius = 1.0;
129 
130 		DVector<Vector3> vertices;
131 		DVector<Vector3> normals;
132 		DVector<Vector2> uvs;
133 		DVector<float> tangents;
134 		Matrix3 tt = Matrix3(Vector3(0, 1, 0), Math_PI * 0.5);
135 
136 		for (int i = 1; i <= lats; i++) {
137 			double lat0 = Math_PI * (-0.5 + (double)(i - 1) / lats);
138 			double z0 = Math::sin(lat0);
139 			double zr0 = Math::cos(lat0);
140 
141 			double lat1 = Math_PI * (-0.5 + (double)i / lats);
142 			double z1 = Math::sin(lat1);
143 			double zr1 = Math::cos(lat1);
144 
145 			for (int j = lons; j >= 1; j--) {
146 
147 				double lng0 = 2 * Math_PI * (double)(j - 1) / lons;
148 				double x0 = Math::cos(lng0);
149 				double y0 = Math::sin(lng0);
150 
151 				double lng1 = 2 * Math_PI * (double)(j) / lons;
152 				double x1 = Math::cos(lng1);
153 				double y1 = Math::sin(lng1);
154 
155 				Vector3 v[4] = {
156 					Vector3(x1 * zr0, z0, y1 * zr0),
157 					Vector3(x1 * zr1, z1, y1 * zr1),
158 					Vector3(x0 * zr1, z1, y0 * zr1),
159 					Vector3(x0 * zr0, z0, y0 * zr0)
160 				};
161 
162 #define ADD_POINT(m_idx)                                                                       \
163 	normals.push_back(v[m_idx]);                                                               \
164 	vertices.push_back(v[m_idx] * radius);                                                     \
165 	{                                                                                          \
166 		Vector2 uv(Math::atan2(v[m_idx].x, v[m_idx].z), Math::atan2(-v[m_idx].y, v[m_idx].z)); \
167 		uv /= Math_PI;                                                                         \
168 		uv *= 4.0;                                                                             \
169 		uv = uv * 0.5 + Vector2(0.5, 0.5);                                                     \
170 		uvs.push_back(uv);                                                                     \
171 	}                                                                                          \
172 	{                                                                                          \
173 		Vector3 t = tt.xform(v[m_idx]);                                                        \
174 		tangents.push_back(t.x);                                                               \
175 		tangents.push_back(t.y);                                                               \
176 		tangents.push_back(t.z);                                                               \
177 		tangents.push_back(1.0);                                                               \
178 	}
179 
180 				ADD_POINT(0);
181 				ADD_POINT(1);
182 				ADD_POINT(2);
183 
184 				ADD_POINT(2);
185 				ADD_POINT(3);
186 				ADD_POINT(0);
187 			}
188 		}
189 
190 		Array arr;
191 		arr.resize(VS::ARRAY_MAX);
192 		arr[VS::ARRAY_VERTEX] = vertices;
193 		arr[VS::ARRAY_NORMAL] = normals;
194 		arr[VS::ARRAY_TANGENT] = tangents;
195 		arr[VS::ARRAY_TEX_UV] = uvs;
196 
197 		sphere_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, arr);
198 
199 		sphere_instance->set_mesh(sphere_mesh);
200 	}
201 	{
202 
203 		box_mesh.instance();
204 
205 		DVector<Vector3> vertices;
206 		DVector<Vector3> normals;
207 		DVector<float> tangents;
208 		DVector<Vector3> uvs;
209 
210 		int vtx_idx = 0;
211 #define ADD_VTX(m_idx)                                                             \
212 	;                                                                              \
213 	vertices.push_back(face_points[m_idx]);                                        \
214 	normals.push_back(normal_points[m_idx]);                                       \
215 	tangents.push_back(normal_points[m_idx][1]);                                   \
216 	tangents.push_back(normal_points[m_idx][2]);                                   \
217 	tangents.push_back(normal_points[m_idx][0]);                                   \
218 	tangents.push_back(1.0);                                                       \
219 	uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); \
220 	vtx_idx++;
221 
222 		for (int i = 0; i < 6; i++) {
223 
224 			Vector3 face_points[4];
225 			Vector3 normal_points[4];
226 			float uv_points[8] = { 0, 0, 0, 1, 1, 1, 1, 0 };
227 
228 			for (int j = 0; j < 4; j++) {
229 
230 				float v[3];
231 				v[0] = 1.0;
232 				v[1] = 1 - 2 * ((j >> 1) & 1);
233 				v[2] = v[1] * (1 - 2 * (j & 1));
234 
235 				for (int k = 0; k < 3; k++) {
236 
237 					if (i < 3)
238 						face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
239 					else
240 						face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
241 				}
242 				normal_points[j] = Vector3();
243 				normal_points[j][i % 3] = (i >= 3 ? -1 : 1);
244 			}
245 
246 			//tri 1
247 			ADD_VTX(0);
248 			ADD_VTX(1);
249 			ADD_VTX(2);
250 			//tri 2
251 			ADD_VTX(2);
252 			ADD_VTX(3);
253 			ADD_VTX(0);
254 		}
255 
256 		Array d;
257 		d.resize(VS::ARRAY_MAX);
258 		d[VisualServer::ARRAY_NORMAL] = normals;
259 		d[VisualServer::ARRAY_TANGENT] = tangents;
260 		d[VisualServer::ARRAY_TEX_UV] = uvs;
261 		d[VisualServer::ARRAY_VERTEX] = vertices;
262 
263 		DVector<int> indices;
264 		indices.resize(vertices.size());
265 		for (int i = 0; i < vertices.size(); i++)
266 			indices.set(i, i);
267 		d[VisualServer::ARRAY_INDEX] = indices;
268 
269 		box_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES, d);
270 		box_instance->set_mesh(box_mesh);
271 		box_instance->hide();
272 	}
273 
274 	set_custom_minimum_size(Size2(1, 150) * EDSCALE);
275 
276 	HBoxContainer *hb = memnew(HBoxContainer);
277 	add_child(hb);
278 	hb->set_area_as_parent_rect(2);
279 
280 	VBoxContainer *vb_shape = memnew(VBoxContainer);
281 	hb->add_child(vb_shape);
282 
283 	sphere_switch = memnew(TextureButton);
284 	sphere_switch->set_toggle_mode(true);
285 	sphere_switch->set_pressed(true);
286 	vb_shape->add_child(sphere_switch);
287 	sphere_switch->connect("pressed", this, "_button_pressed", varray(sphere_switch));
288 
289 	box_switch = memnew(TextureButton);
290 	box_switch->set_toggle_mode(true);
291 	box_switch->set_pressed(false);
292 	vb_shape->add_child(box_switch);
293 	box_switch->connect("pressed", this, "_button_pressed", varray(box_switch));
294 
295 	hb->add_spacer();
296 
297 	VBoxContainer *vb_light = memnew(VBoxContainer);
298 	hb->add_child(vb_light);
299 
300 	light_1_switch = memnew(TextureButton);
301 	light_1_switch->set_toggle_mode(true);
302 	vb_light->add_child(light_1_switch);
303 	light_1_switch->connect("pressed", this, "_button_pressed", varray(light_1_switch));
304 
305 	light_2_switch = memnew(TextureButton);
306 	light_2_switch->set_toggle_mode(true);
307 	vb_light->add_child(light_2_switch);
308 	light_2_switch->connect("pressed", this, "_button_pressed", varray(light_2_switch));
309 
310 	first_enter = true;
311 }
312 
edit(Object * p_object)313 void MaterialEditorPlugin::edit(Object *p_object) {
314 
315 	Material *s = p_object->cast_to<Material>();
316 	if (!s)
317 		return;
318 
319 	material_editor->edit(Ref<Material>(s));
320 }
321 
handles(Object * p_object) const322 bool MaterialEditorPlugin::handles(Object *p_object) const {
323 
324 	return p_object->is_type("Material");
325 }
326 
make_visible(bool p_visible)327 void MaterialEditorPlugin::make_visible(bool p_visible) {
328 
329 	if (p_visible) {
330 		material_editor->show();
331 		//		material_editor->set_process(true);
332 	} else {
333 
334 		material_editor->hide();
335 		//		material_editor->set_process(false);
336 	}
337 }
338 
MaterialEditorPlugin(EditorNode * p_node)339 MaterialEditorPlugin::MaterialEditorPlugin(EditorNode *p_node) {
340 
341 	editor = p_node;
342 	material_editor = memnew(MaterialEditor);
343 	add_control_to_container(CONTAINER_PROPERTY_EDITOR_BOTTOM, material_editor);
344 	material_editor->hide();
345 }
346 
~MaterialEditorPlugin()347 MaterialEditorPlugin::~MaterialEditorPlugin() {
348 }
349