1 /*************************************************************************/
2 /*  editor_preview_plugins.cpp                                           */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #include "editor_preview_plugins.h"
31 #include "editor/editor_scale.h"
32 #include "editor/editor_settings.h"
33 #include "io/file_access_memory.h"
34 #include "io/resource_loader.h"
35 #include "os/os.h"
36 #include "scene/resources/bit_mask.h"
37 #include "scene/resources/material.h"
38 #include "scene/resources/mesh.h"
39 #include "scene/resources/sample.h"
40 
handles(const String & p_type) const41 bool EditorTexturePreviewPlugin::handles(const String &p_type) const {
42 
43 	return (ObjectTypeDB::is_type(p_type, "ImageTexture") || ObjectTypeDB::is_type(p_type, "AtlasTexture"));
44 }
45 
generate(const RES & p_from)46 Ref<Texture> EditorTexturePreviewPlugin::generate(const RES &p_from) {
47 
48 	Image img;
49 	Ref<AtlasTexture> atex = p_from;
50 	if (atex.is_valid()) {
51 		Ref<ImageTexture> tex = atex->get_atlas();
52 		if (!tex.is_valid()) {
53 			return Ref<Texture>();
54 		}
55 		Image atlas = tex->get_data();
56 		img = atlas.get_rect(atex->get_region());
57 	} else {
58 		Ref<ImageTexture> tex = p_from;
59 		img = tex->get_data();
60 	}
61 
62 	if (img.empty())
63 		return Ref<Texture>();
64 
65 	img.clear_mipmaps();
66 
67 	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
68 	thumbnail_size *= EDSCALE;
69 	if (img.is_compressed()) {
70 		if (img.decompress() != OK)
71 			return Ref<Texture>();
72 	} else if (img.get_format() != Image::FORMAT_RGB && img.get_format() != Image::FORMAT_RGBA) {
73 		img.convert(Image::FORMAT_RGBA);
74 	}
75 
76 	int width, height;
77 	if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
78 
79 		width = thumbnail_size;
80 		height = img.get_height() * thumbnail_size / img.get_width();
81 	} else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) {
82 
83 		height = thumbnail_size;
84 		width = img.get_width() * thumbnail_size / img.get_height();
85 	} else {
86 
87 		width = img.get_width();
88 		height = img.get_height();
89 	}
90 
91 	img.resize(width, height);
92 
93 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
94 
95 	ptex->create_from_image(img, 0);
96 	return ptex;
97 }
98 
EditorTexturePreviewPlugin()99 EditorTexturePreviewPlugin::EditorTexturePreviewPlugin() {
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////
103 
handles(const String & p_type) const104 bool EditorBitmapPreviewPlugin::handles(const String &p_type) const {
105 
106 	return ObjectTypeDB::is_type(p_type, "BitMap");
107 }
108 
generate(const RES & p_from)109 Ref<Texture> EditorBitmapPreviewPlugin::generate(const RES &p_from) {
110 
111 	Ref<BitMap> bm = p_from;
112 
113 	if (bm->get_size() == Size2()) {
114 		return Ref<Texture>();
115 	}
116 
117 	DVector<uint8_t> data;
118 
119 	data.resize(bm->get_size().width * bm->get_size().height);
120 
121 	{
122 		DVector<uint8_t>::Write w = data.write();
123 
124 		for (int i = 0; i < bm->get_size().width; i++) {
125 			for (int j = 0; j < bm->get_size().height; j++) {
126 				if (bm->get_bit(Point2i(i, j))) {
127 					w[j * bm->get_size().width + i] = 255;
128 				} else {
129 					w[j * bm->get_size().width + i] = 0;
130 				}
131 			}
132 		}
133 	}
134 
135 	Image img(bm->get_size().width, bm->get_size().height, 0, Image::FORMAT_GRAYSCALE, data);
136 
137 	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
138 	thumbnail_size *= EDSCALE;
139 	if (img.is_compressed()) {
140 		if (img.decompress() != OK)
141 			return Ref<Texture>();
142 	} else if (img.get_format() != Image::FORMAT_RGB && img.get_format() != Image::FORMAT_RGBA) {
143 		img.convert(Image::FORMAT_RGBA);
144 	}
145 
146 	int width, height;
147 	if (img.get_width() > thumbnail_size && img.get_width() >= img.get_height()) {
148 
149 		width = thumbnail_size;
150 		height = img.get_height() * thumbnail_size / img.get_width();
151 	} else if (img.get_height() > thumbnail_size && img.get_height() >= img.get_width()) {
152 
153 		height = thumbnail_size;
154 		width = img.get_width() * thumbnail_size / img.get_height();
155 	} else {
156 
157 		width = img.get_width();
158 		height = img.get_height();
159 	}
160 
161 	img.resize(width, height);
162 
163 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
164 
165 	ptex->create_from_image(img, 0);
166 	return ptex;
167 }
168 
EditorBitmapPreviewPlugin()169 EditorBitmapPreviewPlugin::EditorBitmapPreviewPlugin() {
170 }
171 
172 ///////////////////////////////////////////////////////////////////////////
173 
_gen_from_imd(Ref<ResourceImportMetadata> p_imd)174 Ref<Texture> EditorPackedScenePreviewPlugin::_gen_from_imd(Ref<ResourceImportMetadata> p_imd) {
175 
176 	if (p_imd.is_null()) {
177 		return Ref<Texture>();
178 	}
179 
180 	if (!p_imd->has_option("thumbnail"))
181 		return Ref<Texture>();
182 
183 	Variant tn = p_imd->get_option("thumbnail");
184 	//print_line(Variant::get_type_name(tn.get_type()));
185 	DVector<uint8_t> thumbnail = tn;
186 
187 	int len = thumbnail.size();
188 	if (len == 0)
189 		return Ref<Texture>();
190 
191 	DVector<uint8_t>::Read r = thumbnail.read();
192 
193 	Image img(r.ptr(), len);
194 	if (img.empty())
195 		return Ref<Texture>();
196 
197 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
198 	ptex->create_from_image(img, 0);
199 	return ptex;
200 }
201 
handles(const String & p_type) const202 bool EditorPackedScenePreviewPlugin::handles(const String &p_type) const {
203 
204 	return ObjectTypeDB::is_type(p_type, "PackedScene");
205 }
generate(const RES & p_from)206 Ref<Texture> EditorPackedScenePreviewPlugin::generate(const RES &p_from) {
207 
208 	Ref<ResourceImportMetadata> imd = p_from->get_import_metadata();
209 	return _gen_from_imd(imd);
210 }
211 
generate_from_path(const String & p_path)212 Ref<Texture> EditorPackedScenePreviewPlugin::generate_from_path(const String &p_path) {
213 
214 	Ref<ResourceImportMetadata> imd = ResourceLoader::load_import_metadata(p_path);
215 	return _gen_from_imd(imd);
216 }
217 
EditorPackedScenePreviewPlugin()218 EditorPackedScenePreviewPlugin::EditorPackedScenePreviewPlugin() {
219 }
220 
221 //////////////////////////////////////////////////////////////////
222 
handles(const String & p_type) const223 bool EditorMaterialPreviewPlugin::handles(const String &p_type) const {
224 
225 	return ObjectTypeDB::is_type(p_type, "Material"); //any material
226 }
227 
generate(const RES & p_from)228 Ref<Texture> EditorMaterialPreviewPlugin::generate(const RES &p_from) {
229 
230 	Ref<Material> material = p_from;
231 	ERR_FAIL_COND_V(material.is_null(), Ref<Texture>());
232 
233 	VS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid());
234 
235 	VS::get_singleton()->viewport_queue_screen_capture(viewport);
236 	VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
237 	//	print_line("queue capture!");
238 	Image img;
239 
240 	int timeout = 1000;
241 	while (timeout) {
242 		//print_line("try capture?");
243 		OS::get_singleton()->delay_usec(10);
244 		img = VS::get_singleton()->viewport_get_screen_capture(viewport);
245 		if (!img.empty())
246 			break;
247 		timeout--;
248 	}
249 
250 	//print_line("captured!");
251 	VS::get_singleton()->mesh_surface_set_material(sphere, 0, RID());
252 
253 	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
254 	thumbnail_size *= EDSCALE;
255 	img.resize(thumbnail_size, thumbnail_size);
256 
257 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
258 	ptex->create_from_image(img, 0);
259 	return ptex;
260 }
261 
EditorMaterialPreviewPlugin()262 EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
263 
264 	scenario = VS::get_singleton()->scenario_create();
265 
266 	viewport = VS::get_singleton()->viewport_create();
267 	VS::get_singleton()->viewport_set_as_render_target(viewport, true);
268 	VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_DISABLED);
269 	VS::get_singleton()->viewport_set_scenario(viewport, scenario);
270 	VS::ViewportRect vr;
271 	vr.x = 0;
272 	vr.y = 0;
273 	vr.width = 128;
274 	vr.height = 128;
275 	VS::get_singleton()->viewport_set_rect(viewport, vr);
276 
277 	camera = VS::get_singleton()->camera_create();
278 	VS::get_singleton()->viewport_attach_camera(viewport, camera);
279 	VS::get_singleton()->camera_set_transform(camera, Transform(Matrix3(), Vector3(0, 0, 3)));
280 	VS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10);
281 
282 	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
283 	light_instance = VS::get_singleton()->instance_create2(light, scenario);
284 	VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
285 
286 	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
287 	VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_DIFFUSE, Color(0.7, 0.7, 0.7));
288 	VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
289 	light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
290 
291 	VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
292 
293 	sphere = VS::get_singleton()->mesh_create();
294 	sphere_instance = VS::get_singleton()->instance_create2(sphere, scenario);
295 
296 	int lats = 32;
297 	int lons = 32;
298 	float radius = 1.0;
299 
300 	DVector<Vector3> vertices;
301 	DVector<Vector3> normals;
302 	DVector<Vector2> uvs;
303 	DVector<float> tangents;
304 	Matrix3 tt = Matrix3(Vector3(0, 1, 0), Math_PI * 0.5);
305 
306 	for (int i = 1; i <= lats; i++) {
307 		double lat0 = Math_PI * (-0.5 + (double)(i - 1) / lats);
308 		double z0 = Math::sin(lat0);
309 		double zr0 = Math::cos(lat0);
310 
311 		double lat1 = Math_PI * (-0.5 + (double)i / lats);
312 		double z1 = Math::sin(lat1);
313 		double zr1 = Math::cos(lat1);
314 
315 		for (int j = lons; j >= 1; j--) {
316 
317 			double lng0 = 2 * Math_PI * (double)(j - 1) / lons;
318 			double x0 = Math::cos(lng0);
319 			double y0 = Math::sin(lng0);
320 
321 			double lng1 = 2 * Math_PI * (double)(j) / lons;
322 			double x1 = Math::cos(lng1);
323 			double y1 = Math::sin(lng1);
324 
325 			Vector3 v[4] = {
326 				Vector3(x1 * zr0, z0, y1 * zr0),
327 				Vector3(x1 * zr1, z1, y1 * zr1),
328 				Vector3(x0 * zr1, z1, y0 * zr1),
329 				Vector3(x0 * zr0, z0, y0 * zr0)
330 			};
331 
332 #define ADD_POINT(m_idx)                                                                       \
333 	normals.push_back(v[m_idx]);                                                               \
334 	vertices.push_back(v[m_idx] * radius);                                                     \
335 	{                                                                                          \
336 		Vector2 uv(Math::atan2(v[m_idx].x, v[m_idx].z), Math::atan2(-v[m_idx].y, v[m_idx].z)); \
337 		uv /= Math_PI;                                                                         \
338 		uv *= 4.0;                                                                             \
339 		uv = uv * 0.5 + Vector2(0.5, 0.5);                                                     \
340 		uvs.push_back(uv);                                                                     \
341 	}                                                                                          \
342 	{                                                                                          \
343 		Vector3 t = tt.xform(v[m_idx]);                                                        \
344 		tangents.push_back(t.x);                                                               \
345 		tangents.push_back(t.y);                                                               \
346 		tangents.push_back(t.z);                                                               \
347 		tangents.push_back(1.0);                                                               \
348 	}
349 
350 			ADD_POINT(0);
351 			ADD_POINT(1);
352 			ADD_POINT(2);
353 
354 			ADD_POINT(2);
355 			ADD_POINT(3);
356 			ADD_POINT(0);
357 		}
358 	}
359 
360 	Array arr;
361 	arr.resize(VS::ARRAY_MAX);
362 	arr[VS::ARRAY_VERTEX] = vertices;
363 	arr[VS::ARRAY_NORMAL] = normals;
364 	arr[VS::ARRAY_TANGENT] = tangents;
365 	arr[VS::ARRAY_TEX_UV] = uvs;
366 	VS::get_singleton()->mesh_add_surface(sphere, VS::PRIMITIVE_TRIANGLES, arr);
367 }
368 
~EditorMaterialPreviewPlugin()369 EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() {
370 
371 	VS::get_singleton()->free(sphere);
372 	VS::get_singleton()->free(sphere_instance);
373 	VS::get_singleton()->free(viewport);
374 	VS::get_singleton()->free(light);
375 	VS::get_singleton()->free(light_instance);
376 	VS::get_singleton()->free(light2);
377 	VS::get_singleton()->free(light_instance2);
378 	VS::get_singleton()->free(camera);
379 	VS::get_singleton()->free(scenario);
380 }
381 
382 ///////////////////////////////////////////////////////////////////////////
383 
_is_text_char(CharType c)384 static bool _is_text_char(CharType c) {
385 
386 	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
387 }
388 
handles(const String & p_type) const389 bool EditorScriptPreviewPlugin::handles(const String &p_type) const {
390 
391 	return ObjectTypeDB::is_type(p_type, "Script");
392 }
393 
generate(const RES & p_from)394 Ref<Texture> EditorScriptPreviewPlugin::generate(const RES &p_from) {
395 
396 	Ref<Script> scr = p_from;
397 	if (scr.is_null())
398 		return Ref<Texture>();
399 
400 	String code = scr->get_source_code().strip_edges();
401 	if (code == "")
402 		return Ref<Texture>();
403 
404 	List<String> kwors;
405 	scr->get_language()->get_reserved_words(&kwors);
406 
407 	Set<String> keywords;
408 
409 	for (List<String>::Element *E = kwors.front(); E; E = E->next()) {
410 
411 		keywords.insert(E->get());
412 	}
413 
414 	int line = 0;
415 	int col = 0;
416 	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
417 	thumbnail_size *= EDSCALE;
418 	Image img(thumbnail_size, thumbnail_size, 0, Image::FORMAT_RGBA);
419 
420 	Color bg_color = EditorSettings::get_singleton()->get("text_editor/background_color");
421 	bg_color.a = 1.0;
422 	Color keyword_color = EditorSettings::get_singleton()->get("text_editor/keyword_color");
423 	Color text_color = EditorSettings::get_singleton()->get("text_editor/text_color");
424 	Color symbol_color = EditorSettings::get_singleton()->get("text_editor/symbol_color");
425 
426 	for (int i = 0; i < thumbnail_size; i++) {
427 		for (int j = 0; j < thumbnail_size; j++) {
428 			img.put_pixel(i, j, bg_color);
429 		}
430 	}
431 
432 	bool prev_is_text = false;
433 	bool in_keyword = false;
434 	for (int i = 0; i < code.length(); i++) {
435 
436 		CharType c = code[i];
437 		if (c > 32) {
438 			if (col < thumbnail_size) {
439 				Color color = text_color;
440 
441 				if (c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t')) {
442 					//make symbol a little visible
443 					color = symbol_color;
444 					in_keyword = false;
445 				} else if (!prev_is_text && _is_text_char(c)) {
446 					int pos = i;
447 
448 					while (_is_text_char(code[pos])) {
449 						pos++;
450 					}
451 					///print_line("from "+itos(i)+" to "+itos(pos));
452 					String word = code.substr(i, pos - i);
453 					//print_line("found word: "+word);
454 					if (keywords.has(word))
455 						in_keyword = true;
456 
457 				} else if (!_is_text_char(c)) {
458 					in_keyword = false;
459 				}
460 
461 				if (in_keyword)
462 					color = keyword_color;
463 
464 				Color ul = color;
465 				ul.a *= 0.5;
466 				img.put_pixel(col, line * 2, bg_color.blend(ul));
467 				img.put_pixel(col, line * 2 + 1, color);
468 
469 				prev_is_text = _is_text_char(c);
470 			}
471 		} else {
472 
473 			prev_is_text = false;
474 			in_keyword = false;
475 
476 			if (c == '\n') {
477 				col = 0;
478 				line++;
479 				if (line >= thumbnail_size / 2)
480 					break;
481 			} else if (c == '\t') {
482 				col += 3;
483 			}
484 		}
485 		col++;
486 	}
487 
488 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
489 
490 	ptex->create_from_image(img, 0);
491 	return ptex;
492 }
493 
EditorScriptPreviewPlugin()494 EditorScriptPreviewPlugin::EditorScriptPreviewPlugin() {
495 }
496 ///////////////////////////////////////////////////////////////////
497 
handles(const String & p_type) const498 bool EditorSamplePreviewPlugin::handles(const String &p_type) const {
499 
500 	return ObjectTypeDB::is_type(p_type, "Sample");
501 }
502 
generate(const RES & p_from)503 Ref<Texture> EditorSamplePreviewPlugin::generate(const RES &p_from) {
504 
505 	Ref<Sample> smp = p_from;
506 	ERR_FAIL_COND_V(smp.is_null(), Ref<Texture>());
507 
508 	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
509 	thumbnail_size *= EDSCALE;
510 	DVector<uint8_t> img;
511 	int w = thumbnail_size;
512 	int h = thumbnail_size;
513 	img.resize(w * h * 3);
514 
515 	DVector<uint8_t>::Write imgdata = img.write();
516 	uint8_t *imgw = imgdata.ptr();
517 	DVector<uint8_t> data = smp->get_data();
518 	DVector<uint8_t>::Read sampledata = data.read();
519 	const uint8_t *sdata = sampledata.ptr();
520 
521 	bool stereo = smp->is_stereo();
522 	bool _16 = smp->get_format() == Sample::FORMAT_PCM16;
523 	int len = smp->get_length();
524 
525 	if (len < 1)
526 		return Ref<Texture>();
527 
528 	if (smp->get_format() == Sample::FORMAT_IMA_ADPCM) {
529 
530 		struct IMA_ADPCM_State {
531 
532 			int16_t step_index;
533 			int32_t predictor;
534 			/* values at loop point */
535 			int16_t loop_step_index;
536 			int32_t loop_predictor;
537 			int32_t last_nibble;
538 			int32_t loop_pos;
539 			int32_t window_ofs;
540 			const uint8_t *ptr;
541 		} ima_adpcm;
542 
543 		ima_adpcm.step_index = 0;
544 		ima_adpcm.predictor = 0;
545 		ima_adpcm.loop_step_index = 0;
546 		ima_adpcm.loop_predictor = 0;
547 		ima_adpcm.last_nibble = -1;
548 		ima_adpcm.loop_pos = 0x7FFFFFFF;
549 		ima_adpcm.window_ofs = 0;
550 		ima_adpcm.ptr = NULL;
551 
552 		for (int i = 0; i < w; i++) {
553 
554 			float max[2] = { -1e10, -1e10 };
555 			float min[2] = { 1e10, 1e10 };
556 			int from = i * len / w;
557 			int to = (i + 1) * len / w;
558 			if (to >= len)
559 				to = len - 1;
560 
561 			for (int j = from; j < to; j++) {
562 
563 				while (j > ima_adpcm.last_nibble) {
564 
565 					static const int16_t _ima_adpcm_step_table[89] = {
566 						7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
567 						19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
568 						50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
569 						130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
570 						337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
571 						876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
572 						2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
573 						5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
574 						15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
575 					};
576 
577 					static const int8_t _ima_adpcm_index_table[16] = {
578 						-1, -1, -1, -1, 2, 4, 6, 8,
579 						-1, -1, -1, -1, 2, 4, 6, 8
580 					};
581 
582 					int16_t nibble, diff, step;
583 
584 					ima_adpcm.last_nibble++;
585 					const uint8_t *src_ptr = sdata;
586 
587 					int ofs = ima_adpcm.last_nibble >> 1;
588 
589 					if (stereo)
590 						ofs *= 2;
591 
592 					nibble = (ima_adpcm.last_nibble & 1) ?
593 									 (src_ptr[ofs] >> 4) :
594 									 (src_ptr[ofs] & 0xF);
595 					step = _ima_adpcm_step_table[ima_adpcm.step_index];
596 
597 					ima_adpcm.step_index += _ima_adpcm_index_table[nibble];
598 					if (ima_adpcm.step_index < 0)
599 						ima_adpcm.step_index = 0;
600 					if (ima_adpcm.step_index > 88)
601 						ima_adpcm.step_index = 88;
602 
603 					diff = step >> 3;
604 					if (nibble & 1)
605 						diff += step >> 2;
606 					if (nibble & 2)
607 						diff += step >> 1;
608 					if (nibble & 4)
609 						diff += step;
610 					if (nibble & 8)
611 						diff = -diff;
612 
613 					ima_adpcm.predictor += diff;
614 					if (ima_adpcm.predictor < -0x8000)
615 						ima_adpcm.predictor = -0x8000;
616 					else if (ima_adpcm.predictor > 0x7FFF)
617 						ima_adpcm.predictor = 0x7FFF;
618 
619 					/* store loop if there */
620 					if (ima_adpcm.last_nibble == ima_adpcm.loop_pos) {
621 
622 						ima_adpcm.loop_step_index = ima_adpcm.step_index;
623 						ima_adpcm.loop_predictor = ima_adpcm.predictor;
624 					}
625 				}
626 
627 				float v = ima_adpcm.predictor / 32767.0;
628 				if (v > max[0])
629 					max[0] = v;
630 				if (v < min[0])
631 					min[0] = v;
632 			}
633 			max[0] *= 0.8;
634 			min[0] *= 0.8;
635 
636 			for (int j = 0; j < h; j++) {
637 				float v = (j / (float)h) * 2.0 - 1.0;
638 				uint8_t *imgofs = &imgw[(uint64_t(j) * w + i) * 3];
639 				if (v > min[0] && v < max[0]) {
640 					imgofs[0] = 255;
641 					imgofs[1] = 150;
642 					imgofs[2] = 80;
643 				} else {
644 					imgofs[0] = 0;
645 					imgofs[1] = 0;
646 					imgofs[2] = 0;
647 				}
648 			}
649 		}
650 	} else {
651 		for (int i = 0; i < w; i++) {
652 			// i trust gcc will optimize this loop
653 			float max[2] = { -1e10, -1e10 };
654 			float min[2] = { 1e10, 1e10 };
655 			int c = stereo ? 2 : 1;
656 			int from = uint64_t(i) * len / w;
657 			int to = (uint64_t(i) + 1) * len / w;
658 			if (to >= len)
659 				to = len - 1;
660 
661 			if (_16) {
662 				const int16_t *src = (const int16_t *)sdata;
663 
664 				for (int j = 0; j < c; j++) {
665 
666 					for (int k = from; k <= to; k++) {
667 
668 						float v = src[uint64_t(k) * c + j] / 32768.0;
669 						if (v > max[j])
670 							max[j] = v;
671 						if (v < min[j])
672 							min[j] = v;
673 					}
674 				}
675 			} else {
676 
677 				const int8_t *src = (const int8_t *)sdata;
678 
679 				for (int j = 0; j < c; j++) {
680 
681 					for (int k = from; k <= to; k++) {
682 
683 						float v = src[uint64_t(k) * c + j] / 128.0;
684 						if (v > max[j])
685 							max[j] = v;
686 						if (v < min[j])
687 							min[j] = v;
688 					}
689 				}
690 			}
691 
692 			max[0] *= 0.8;
693 			max[1] *= 0.8;
694 			min[0] *= 0.8;
695 			min[1] *= 0.8;
696 
697 			if (!stereo) {
698 				for (int j = 0; j < h; j++) {
699 					float v = (j / (float)h) * 2.0 - 1.0;
700 					uint8_t *imgofs = &imgw[(j * w + i) * 3];
701 					if (v > min[0] && v < max[0]) {
702 						imgofs[0] = 255;
703 						imgofs[1] = 150;
704 						imgofs[2] = 80;
705 					} else {
706 						imgofs[0] = 0;
707 						imgofs[1] = 0;
708 						imgofs[2] = 0;
709 					}
710 				}
711 			} else {
712 
713 				for (int j = 0; j < h; j++) {
714 
715 					int half;
716 					float v;
717 					if (j < (h / 2)) {
718 						half = 0;
719 						v = (j / (float)(h / 2)) * 2.0 - 1.0;
720 					} else {
721 						half = 1;
722 						if ((float)(h / 2) != 0) {
723 							v = ((j - (h / 2)) / (float)(h / 2)) * 2.0 - 1.0;
724 						} else {
725 							v = ((j - (h / 2)) / (float)(1 / 2)) * 2.0 - 1.0;
726 						}
727 					}
728 
729 					uint8_t *imgofs = &imgw[(j * w + i) * 3];
730 					if (v > min[half] && v < max[half]) {
731 						imgofs[0] = 255;
732 						imgofs[1] = 150;
733 						imgofs[2] = 80;
734 					} else {
735 						imgofs[0] = 0;
736 						imgofs[1] = 0;
737 						imgofs[2] = 0;
738 					}
739 				}
740 			}
741 		}
742 	}
743 
744 	imgdata = DVector<uint8_t>::Write();
745 
746 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
747 	ptex->create_from_image(Image(w, h, 0, Image::FORMAT_RGB, img), 0);
748 	return ptex;
749 }
750 
EditorSamplePreviewPlugin()751 EditorSamplePreviewPlugin::EditorSamplePreviewPlugin() {
752 }
753 
754 ///////////////////////////////////////////////////////////////////////////
755 
handles(const String & p_type) const756 bool EditorMeshPreviewPlugin::handles(const String &p_type) const {
757 
758 	return ObjectTypeDB::is_type(p_type, "Mesh"); //any Mesh
759 }
760 
generate(const RES & p_from)761 Ref<Texture> EditorMeshPreviewPlugin::generate(const RES &p_from) {
762 
763 	Ref<Mesh> mesh = p_from;
764 	ERR_FAIL_COND_V(mesh.is_null(), Ref<Texture>());
765 
766 	VS::get_singleton()->instance_set_base(mesh_instance, mesh->get_rid());
767 
768 	AABB aabb = mesh->get_aabb();
769 	Vector3 ofs = aabb.pos + aabb.size * 0.5;
770 	aabb.pos -= ofs;
771 	Transform xform;
772 	xform.basis = Matrix3().rotated(Vector3(0, 1, 0), Math_PI * 0.125);
773 	xform.basis = Matrix3().rotated(Vector3(1, 0, 0), -Math_PI * 0.125) * xform.basis;
774 	AABB rot_aabb = xform.xform(aabb);
775 	float m = MAX(rot_aabb.size.x, rot_aabb.size.y) * 0.5;
776 	if (m == 0)
777 		return Ref<Texture>();
778 	m = 1.0 / m;
779 	m *= 0.5;
780 	//print_line("scale: "+rtos(m));
781 	xform.basis.scale(Vector3(m, m, m));
782 	xform.origin = -xform.basis.xform(ofs); //-ofs*m;
783 	xform.origin.z -= rot_aabb.size.z * 2;
784 	VS::get_singleton()->instance_set_transform(mesh_instance, xform);
785 
786 	VS::get_singleton()->viewport_queue_screen_capture(viewport);
787 	VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_ONCE); //once used for capture
788 	//	print_line("queue capture!");
789 	Image img;
790 
791 	int timeout = 1000;
792 	while (timeout) {
793 		//print_line("try capture?");
794 		OS::get_singleton()->delay_usec(10);
795 		img = VS::get_singleton()->viewport_get_screen_capture(viewport);
796 		if (!img.empty())
797 			break;
798 		timeout--;
799 	}
800 
801 	//print_line("captured!");
802 	VS::get_singleton()->instance_set_base(mesh_instance, RID());
803 
804 	int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size");
805 	thumbnail_size *= EDSCALE;
806 	img.resize(thumbnail_size, thumbnail_size);
807 
808 	Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture));
809 	ptex->create_from_image(img, 0);
810 	return ptex;
811 }
812 
EditorMeshPreviewPlugin()813 EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() {
814 
815 	scenario = VS::get_singleton()->scenario_create();
816 	viewport = VS::get_singleton()->viewport_create();
817 	VS::get_singleton()->viewport_set_as_render_target(viewport, true);
818 	VS::get_singleton()->viewport_set_render_target_update_mode(viewport, VS::RENDER_TARGET_UPDATE_DISABLED);
819 	VS::get_singleton()->viewport_set_scenario(viewport, scenario);
820 	VS::ViewportRect vr;
821 	vr.x = 0;
822 	vr.y = 0;
823 	vr.width = 128;
824 	vr.height = 128;
825 	VS::get_singleton()->viewport_set_rect(viewport, vr);
826 
827 	camera = VS::get_singleton()->camera_create();
828 	VS::get_singleton()->viewport_attach_camera(viewport, camera);
829 	VS::get_singleton()->camera_set_transform(camera, Transform(Matrix3(), Vector3(0, 0, 3)));
830 	//	VS::get_singleton()->camera_set_perspective(camera,45,0.1,10);
831 	VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0);
832 
833 	light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
834 	light_instance = VS::get_singleton()->instance_create2(light, scenario);
835 	VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0)));
836 
837 	light2 = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL);
838 	VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_DIFFUSE, Color(0.7, 0.7, 0.7));
839 	VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0));
840 	light_instance2 = VS::get_singleton()->instance_create2(light2, scenario);
841 
842 	VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1)));
843 
844 	//	sphere = VS::get_singleton()->mesh_create();
845 	mesh_instance = VS::get_singleton()->instance_create();
846 	VS::get_singleton()->instance_set_scenario(mesh_instance, scenario);
847 }
848 
~EditorMeshPreviewPlugin()849 EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() {
850 
851 	//VS::get_singleton()->free(sphere);
852 	VS::get_singleton()->free(mesh_instance);
853 	VS::get_singleton()->free(viewport);
854 	VS::get_singleton()->free(light);
855 	VS::get_singleton()->free(light_instance);
856 	VS::get_singleton()->free(light2);
857 	VS::get_singleton()->free(light_instance2);
858 	VS::get_singleton()->free(camera);
859 	VS::get_singleton()->free(scenario);
860 }
861