primitive_meshes.cpp 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. /**************************************************************************/
  2. /* primitive_meshes.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  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 "primitive_meshes.h"
  31. #include "core/core_string_names.h"
  32. #include "core/os/main_loop.h"
  33. #include "scene/resources/theme.h"
  34. #include "servers/visual_server.h"
  35. #include "thirdparty/misc/clipper.hpp"
  36. #include "thirdparty/misc/triangulator.h"
  37. /**
  38. PrimitiveMesh
  39. */
  40. void PrimitiveMesh::_update() const {
  41. Array arr;
  42. arr.resize(VS::ARRAY_MAX);
  43. _create_mesh_array(arr);
  44. PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX];
  45. aabb = AABB();
  46. int pc = points.size();
  47. ERR_FAIL_COND(pc == 0);
  48. {
  49. PoolVector<Vector3>::Read r = points.read();
  50. for (int i = 0; i < pc; i++) {
  51. if (i == 0) {
  52. aabb.position = r[i];
  53. } else {
  54. aabb.expand_to(r[i]);
  55. }
  56. }
  57. }
  58. if (flip_faces) {
  59. PoolVector<Vector3> normals = arr[VS::ARRAY_NORMAL];
  60. PoolVector<int> indices = arr[VS::ARRAY_INDEX];
  61. if (normals.size() && indices.size()) {
  62. {
  63. int nc = normals.size();
  64. PoolVector<Vector3>::Write w = normals.write();
  65. for (int i = 0; i < nc; i++) {
  66. w[i] = -w[i];
  67. }
  68. }
  69. {
  70. int ic = indices.size();
  71. PoolVector<int>::Write w = indices.write();
  72. for (int i = 0; i < ic; i += 3) {
  73. SWAP(w[i + 0], w[i + 1]);
  74. }
  75. }
  76. arr[VS::ARRAY_NORMAL] = normals;
  77. arr[VS::ARRAY_INDEX] = indices;
  78. }
  79. }
  80. // in with the new
  81. VisualServer::get_singleton()->mesh_clear(mesh);
  82. VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr);
  83. VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  84. pending_request = false;
  85. clear_cache();
  86. const_cast<PrimitiveMesh *>(this)->emit_changed();
  87. }
  88. void PrimitiveMesh::_request_update() {
  89. if (pending_request) {
  90. return;
  91. }
  92. _update();
  93. }
  94. int PrimitiveMesh::get_surface_count() const {
  95. if (pending_request) {
  96. _update();
  97. }
  98. return 1;
  99. }
  100. int PrimitiveMesh::surface_get_array_len(int p_idx) const {
  101. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  102. if (pending_request) {
  103. _update();
  104. }
  105. return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, 0);
  106. }
  107. int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
  108. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  109. if (pending_request) {
  110. _update();
  111. }
  112. return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
  113. }
  114. Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
  115. ERR_FAIL_INDEX_V(p_surface, 1, Array());
  116. if (pending_request) {
  117. _update();
  118. }
  119. return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0);
  120. }
  121. Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
  122. ERR_FAIL_INDEX_V(p_surface, 1, Array());
  123. if (pending_request) {
  124. _update();
  125. }
  126. return Array();
  127. }
  128. uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
  129. ERR_FAIL_INDEX_V(p_idx, 1, 0);
  130. if (pending_request) {
  131. _update();
  132. }
  133. return VisualServer::get_singleton()->mesh_surface_get_format(mesh, 0);
  134. }
  135. Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
  136. return primitive_type;
  137. }
  138. void PrimitiveMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
  139. ERR_FAIL_INDEX(p_idx, 1);
  140. set_material(p_material);
  141. }
  142. Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const {
  143. ERR_FAIL_INDEX_V(p_idx, 1, nullptr);
  144. return material;
  145. }
  146. int PrimitiveMesh::get_blend_shape_count() const {
  147. return 0;
  148. }
  149. StringName PrimitiveMesh::get_blend_shape_name(int p_index) const {
  150. return StringName();
  151. }
  152. void PrimitiveMesh::set_blend_shape_name(int p_index, const StringName &p_name) {
  153. }
  154. AABB PrimitiveMesh::get_aabb() const {
  155. if (pending_request) {
  156. _update();
  157. }
  158. return aabb;
  159. }
  160. RID PrimitiveMesh::get_rid() const {
  161. if (pending_request) {
  162. _update();
  163. }
  164. return mesh;
  165. }
  166. void PrimitiveMesh::_bind_methods() {
  167. ClassDB::bind_method(D_METHOD("_update"), &PrimitiveMesh::_update);
  168. ClassDB::bind_method(D_METHOD("set_material", "material"), &PrimitiveMesh::set_material);
  169. ClassDB::bind_method(D_METHOD("get_material"), &PrimitiveMesh::get_material);
  170. ClassDB::bind_method(D_METHOD("get_mesh_arrays"), &PrimitiveMesh::get_mesh_arrays);
  171. ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &PrimitiveMesh::set_custom_aabb);
  172. ClassDB::bind_method(D_METHOD("get_custom_aabb"), &PrimitiveMesh::get_custom_aabb);
  173. ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
  174. ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
  175. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material");
  176. ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
  177. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
  178. }
  179. void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
  180. material = p_material;
  181. if (!pending_request) {
  182. // just apply it, else it'll happen when _update is called.
  183. VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  184. _change_notify();
  185. emit_changed();
  186. };
  187. }
  188. Ref<Material> PrimitiveMesh::get_material() const {
  189. return material;
  190. }
  191. Array PrimitiveMesh::get_mesh_arrays() const {
  192. return surface_get_arrays(0);
  193. }
  194. void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) {
  195. custom_aabb = p_custom;
  196. VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
  197. emit_changed();
  198. }
  199. AABB PrimitiveMesh::get_custom_aabb() const {
  200. return custom_aabb;
  201. }
  202. void PrimitiveMesh::set_flip_faces(bool p_enable) {
  203. flip_faces = p_enable;
  204. _request_update();
  205. }
  206. bool PrimitiveMesh::get_flip_faces() const {
  207. return flip_faces;
  208. }
  209. PrimitiveMesh::PrimitiveMesh() {
  210. flip_faces = false;
  211. // defaults
  212. mesh = RID_PRIME(VisualServer::get_singleton()->mesh_create());
  213. // assume primitive triangles as the type, correct for all but one and it will change this :)
  214. primitive_type = Mesh::PRIMITIVE_TRIANGLES;
  215. // make sure we do an update after we've finished constructing our object
  216. pending_request = true;
  217. }
  218. PrimitiveMesh::~PrimitiveMesh() {
  219. VisualServer::get_singleton()->free(mesh);
  220. }
  221. /**
  222. CapsuleMesh
  223. */
  224. void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
  225. create_mesh_array(p_arr, radius, mid_height, radial_segments, rings);
  226. }
  227. void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float mid_height, const int radial_segments, const int rings) {
  228. int i, j, prevrow, thisrow, point;
  229. float x, y, z, u, v, w;
  230. float onethird = 1.0 / 3.0;
  231. float twothirds = 2.0 / 3.0;
  232. // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
  233. PoolVector<Vector3> points;
  234. PoolVector<Vector3> normals;
  235. PoolVector<float> tangents;
  236. PoolVector<Vector2> uvs;
  237. PoolVector<int> indices;
  238. point = 0;
  239. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  240. tangents.push_back(m_x); \
  241. tangents.push_back(m_y); \
  242. tangents.push_back(m_z); \
  243. tangents.push_back(m_d);
  244. /* top hemisphere */
  245. thisrow = 0;
  246. prevrow = 0;
  247. for (j = 0; j <= (rings + 1); j++) {
  248. v = j;
  249. v /= (rings + 1);
  250. w = sin(0.5 * Math_PI * v);
  251. z = radius * cos(0.5 * Math_PI * v);
  252. for (i = 0; i <= radial_segments; i++) {
  253. u = i;
  254. u /= radial_segments;
  255. x = sin(u * (Math_PI * 2.0));
  256. y = -cos(u * (Math_PI * 2.0));
  257. Vector3 p = Vector3(x * radius * w, y * radius * w, z);
  258. points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height));
  259. normals.push_back(p.normalized());
  260. ADD_TANGENT(-y, x, 0.0, 1.0)
  261. uvs.push_back(Vector2(u, v * onethird));
  262. point++;
  263. if (i > 0 && j > 0) {
  264. indices.push_back(prevrow + i - 1);
  265. indices.push_back(prevrow + i);
  266. indices.push_back(thisrow + i - 1);
  267. indices.push_back(prevrow + i);
  268. indices.push_back(thisrow + i);
  269. indices.push_back(thisrow + i - 1);
  270. };
  271. };
  272. prevrow = thisrow;
  273. thisrow = point;
  274. };
  275. /* cylinder */
  276. thisrow = point;
  277. prevrow = 0;
  278. for (j = 0; j <= (rings + 1); j++) {
  279. v = j;
  280. v /= (rings + 1);
  281. z = mid_height * v;
  282. z = (mid_height * 0.5) - z;
  283. for (i = 0; i <= radial_segments; i++) {
  284. u = i;
  285. u /= radial_segments;
  286. x = sin(u * (Math_PI * 2.0));
  287. y = -cos(u * (Math_PI * 2.0));
  288. Vector3 p = Vector3(x * radius, y * radius, z);
  289. points.push_back(p);
  290. normals.push_back(Vector3(x, y, 0.0));
  291. ADD_TANGENT(-y, x, 0.0, 1.0)
  292. uvs.push_back(Vector2(u, onethird + (v * onethird)));
  293. point++;
  294. if (i > 0 && j > 0) {
  295. indices.push_back(prevrow + i - 1);
  296. indices.push_back(prevrow + i);
  297. indices.push_back(thisrow + i - 1);
  298. indices.push_back(prevrow + i);
  299. indices.push_back(thisrow + i);
  300. indices.push_back(thisrow + i - 1);
  301. };
  302. };
  303. prevrow = thisrow;
  304. thisrow = point;
  305. };
  306. /* bottom hemisphere */
  307. thisrow = point;
  308. prevrow = 0;
  309. for (j = 0; j <= (rings + 1); j++) {
  310. v = j;
  311. v /= (rings + 1);
  312. v += 1.0;
  313. w = sin(0.5 * Math_PI * v);
  314. z = radius * cos(0.5 * Math_PI * v);
  315. for (i = 0; i <= radial_segments; i++) {
  316. float u2 = i;
  317. u2 /= radial_segments;
  318. x = sin(u2 * (Math_PI * 2.0));
  319. y = -cos(u2 * (Math_PI * 2.0));
  320. Vector3 p = Vector3(x * radius * w, y * radius * w, z);
  321. points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height));
  322. normals.push_back(p.normalized());
  323. ADD_TANGENT(-y, x, 0.0, 1.0)
  324. uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird)));
  325. point++;
  326. if (i > 0 && j > 0) {
  327. indices.push_back(prevrow + i - 1);
  328. indices.push_back(prevrow + i);
  329. indices.push_back(thisrow + i - 1);
  330. indices.push_back(prevrow + i);
  331. indices.push_back(thisrow + i);
  332. indices.push_back(thisrow + i - 1);
  333. };
  334. };
  335. prevrow = thisrow;
  336. thisrow = point;
  337. };
  338. p_arr[VS::ARRAY_VERTEX] = points;
  339. p_arr[VS::ARRAY_NORMAL] = normals;
  340. p_arr[VS::ARRAY_TANGENT] = tangents;
  341. p_arr[VS::ARRAY_TEX_UV] = uvs;
  342. p_arr[VS::ARRAY_INDEX] = indices;
  343. }
  344. void CapsuleMesh::_bind_methods() {
  345. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleMesh::set_radius);
  346. ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleMesh::get_radius);
  347. ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &CapsuleMesh::set_mid_height);
  348. ClassDB::bind_method(D_METHOD("get_mid_height"), &CapsuleMesh::get_mid_height);
  349. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CapsuleMesh::set_radial_segments);
  350. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CapsuleMesh::get_radial_segments);
  351. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings);
  352. ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings);
  353. ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius");
  354. ADD_PROPERTY(PropertyInfo(Variant::REAL, "mid_height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_mid_height", "get_mid_height");
  355. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  356. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  357. }
  358. void CapsuleMesh::set_radius(const float p_radius) {
  359. radius = p_radius;
  360. _request_update();
  361. }
  362. float CapsuleMesh::get_radius() const {
  363. return radius;
  364. }
  365. void CapsuleMesh::set_mid_height(const float p_mid_height) {
  366. mid_height = p_mid_height;
  367. _request_update();
  368. }
  369. float CapsuleMesh::get_mid_height() const {
  370. return mid_height;
  371. }
  372. void CapsuleMesh::set_radial_segments(const int p_segments) {
  373. radial_segments = p_segments > 4 ? p_segments : 4;
  374. _request_update();
  375. }
  376. int CapsuleMesh::get_radial_segments() const {
  377. return radial_segments;
  378. }
  379. void CapsuleMesh::set_rings(const int p_rings) {
  380. rings = p_rings > 1 ? p_rings : 1;
  381. _request_update();
  382. }
  383. int CapsuleMesh::get_rings() const {
  384. return rings;
  385. }
  386. CapsuleMesh::CapsuleMesh() {
  387. // defaults
  388. radius = 1.0;
  389. mid_height = 1.0;
  390. radial_segments = default_radial_segments;
  391. rings = default_rings;
  392. }
  393. /**
  394. CubeMesh
  395. */
  396. void CubeMesh::_create_mesh_array(Array &p_arr) const {
  397. create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d);
  398. }
  399. void CubeMesh::create_mesh_array(Array &p_arr, const Vector3 size, const int subdivide_w, const int subdivide_h, const int subdivide_d) {
  400. int i, j, prevrow, thisrow, point;
  401. float x, y, z;
  402. float onethird = 1.0 / 3.0;
  403. float twothirds = 2.0 / 3.0;
  404. Vector3 start_pos = size * -0.5;
  405. // set our bounding box
  406. PoolVector<Vector3> points;
  407. PoolVector<Vector3> normals;
  408. PoolVector<float> tangents;
  409. PoolVector<Vector2> uvs;
  410. PoolVector<int> indices;
  411. point = 0;
  412. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  413. tangents.push_back(m_x); \
  414. tangents.push_back(m_y); \
  415. tangents.push_back(m_z); \
  416. tangents.push_back(m_d);
  417. // front + back
  418. y = start_pos.y;
  419. thisrow = point;
  420. prevrow = 0;
  421. for (j = 0; j <= subdivide_h + 1; j++) {
  422. x = start_pos.x;
  423. for (i = 0; i <= subdivide_w + 1; i++) {
  424. float u = i;
  425. float v = j;
  426. u /= (3.0 * (subdivide_w + 1.0));
  427. v /= (2.0 * (subdivide_h + 1.0));
  428. // front
  429. points.push_back(Vector3(x, -y, -start_pos.z)); // double negative on the Z!
  430. normals.push_back(Vector3(0.0, 0.0, 1.0));
  431. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  432. uvs.push_back(Vector2(u, v));
  433. point++;
  434. // back
  435. points.push_back(Vector3(-x, -y, start_pos.z));
  436. normals.push_back(Vector3(0.0, 0.0, -1.0));
  437. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  438. uvs.push_back(Vector2(twothirds + u, v));
  439. point++;
  440. if (i > 0 && j > 0) {
  441. int i2 = i * 2;
  442. // front
  443. indices.push_back(prevrow + i2 - 2);
  444. indices.push_back(prevrow + i2);
  445. indices.push_back(thisrow + i2 - 2);
  446. indices.push_back(prevrow + i2);
  447. indices.push_back(thisrow + i2);
  448. indices.push_back(thisrow + i2 - 2);
  449. // back
  450. indices.push_back(prevrow + i2 - 1);
  451. indices.push_back(prevrow + i2 + 1);
  452. indices.push_back(thisrow + i2 - 1);
  453. indices.push_back(prevrow + i2 + 1);
  454. indices.push_back(thisrow + i2 + 1);
  455. indices.push_back(thisrow + i2 - 1);
  456. };
  457. x += size.x / (subdivide_w + 1.0);
  458. };
  459. y += size.y / (subdivide_h + 1.0);
  460. prevrow = thisrow;
  461. thisrow = point;
  462. };
  463. // left + right
  464. y = start_pos.y;
  465. thisrow = point;
  466. prevrow = 0;
  467. for (j = 0; j <= (subdivide_h + 1); j++) {
  468. z = start_pos.z;
  469. for (i = 0; i <= (subdivide_d + 1); i++) {
  470. float u = i;
  471. float v = j;
  472. u /= (3.0 * (subdivide_d + 1.0));
  473. v /= (2.0 * (subdivide_h + 1.0));
  474. // right
  475. points.push_back(Vector3(-start_pos.x, -y, -z));
  476. normals.push_back(Vector3(1.0, 0.0, 0.0));
  477. ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
  478. uvs.push_back(Vector2(onethird + u, v));
  479. point++;
  480. // left
  481. points.push_back(Vector3(start_pos.x, -y, z));
  482. normals.push_back(Vector3(-1.0, 0.0, 0.0));
  483. ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
  484. uvs.push_back(Vector2(u, 0.5 + v));
  485. point++;
  486. if (i > 0 && j > 0) {
  487. int i2 = i * 2;
  488. // right
  489. indices.push_back(prevrow + i2 - 2);
  490. indices.push_back(prevrow + i2);
  491. indices.push_back(thisrow + i2 - 2);
  492. indices.push_back(prevrow + i2);
  493. indices.push_back(thisrow + i2);
  494. indices.push_back(thisrow + i2 - 2);
  495. // left
  496. indices.push_back(prevrow + i2 - 1);
  497. indices.push_back(prevrow + i2 + 1);
  498. indices.push_back(thisrow + i2 - 1);
  499. indices.push_back(prevrow + i2 + 1);
  500. indices.push_back(thisrow + i2 + 1);
  501. indices.push_back(thisrow + i2 - 1);
  502. };
  503. z += size.z / (subdivide_d + 1.0);
  504. };
  505. y += size.y / (subdivide_h + 1.0);
  506. prevrow = thisrow;
  507. thisrow = point;
  508. };
  509. // top + bottom
  510. z = start_pos.z;
  511. thisrow = point;
  512. prevrow = 0;
  513. for (j = 0; j <= (subdivide_d + 1); j++) {
  514. x = start_pos.x;
  515. for (i = 0; i <= (subdivide_w + 1); i++) {
  516. float u = i;
  517. float v = j;
  518. u /= (3.0 * (subdivide_w + 1.0));
  519. v /= (2.0 * (subdivide_d + 1.0));
  520. // top
  521. points.push_back(Vector3(-x, -start_pos.y, -z));
  522. normals.push_back(Vector3(0.0, 1.0, 0.0));
  523. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  524. uvs.push_back(Vector2(onethird + u, 0.5 + v));
  525. point++;
  526. // bottom
  527. points.push_back(Vector3(x, start_pos.y, -z));
  528. normals.push_back(Vector3(0.0, -1.0, 0.0));
  529. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  530. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  531. point++;
  532. if (i > 0 && j > 0) {
  533. int i2 = i * 2;
  534. // top
  535. indices.push_back(prevrow + i2 - 2);
  536. indices.push_back(prevrow + i2);
  537. indices.push_back(thisrow + i2 - 2);
  538. indices.push_back(prevrow + i2);
  539. indices.push_back(thisrow + i2);
  540. indices.push_back(thisrow + i2 - 2);
  541. // bottom
  542. indices.push_back(prevrow + i2 - 1);
  543. indices.push_back(prevrow + i2 + 1);
  544. indices.push_back(thisrow + i2 - 1);
  545. indices.push_back(prevrow + i2 + 1);
  546. indices.push_back(thisrow + i2 + 1);
  547. indices.push_back(thisrow + i2 - 1);
  548. };
  549. x += size.x / (subdivide_w + 1.0);
  550. };
  551. z += size.z / (subdivide_d + 1.0);
  552. prevrow = thisrow;
  553. thisrow = point;
  554. };
  555. p_arr[VS::ARRAY_VERTEX] = points;
  556. p_arr[VS::ARRAY_NORMAL] = normals;
  557. p_arr[VS::ARRAY_TANGENT] = tangents;
  558. p_arr[VS::ARRAY_TEX_UV] = uvs;
  559. p_arr[VS::ARRAY_INDEX] = indices;
  560. }
  561. void CubeMesh::_bind_methods() {
  562. ClassDB::bind_method(D_METHOD("set_size", "size"), &CubeMesh::set_size);
  563. ClassDB::bind_method(D_METHOD("get_size"), &CubeMesh::get_size);
  564. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &CubeMesh::set_subdivide_width);
  565. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &CubeMesh::get_subdivide_width);
  566. ClassDB::bind_method(D_METHOD("set_subdivide_height", "divisions"), &CubeMesh::set_subdivide_height);
  567. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &CubeMesh::get_subdivide_height);
  568. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "divisions"), &CubeMesh::set_subdivide_depth);
  569. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &CubeMesh::get_subdivide_depth);
  570. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size");
  571. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  572. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height");
  573. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  574. }
  575. void CubeMesh::set_size(const Vector3 &p_size) {
  576. size = p_size;
  577. _request_update();
  578. }
  579. Vector3 CubeMesh::get_size() const {
  580. return size;
  581. }
  582. void CubeMesh::set_subdivide_width(const int p_divisions) {
  583. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  584. _request_update();
  585. }
  586. int CubeMesh::get_subdivide_width() const {
  587. return subdivide_w;
  588. }
  589. void CubeMesh::set_subdivide_height(const int p_divisions) {
  590. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  591. _request_update();
  592. }
  593. int CubeMesh::get_subdivide_height() const {
  594. return subdivide_h;
  595. }
  596. void CubeMesh::set_subdivide_depth(const int p_divisions) {
  597. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  598. _request_update();
  599. }
  600. int CubeMesh::get_subdivide_depth() const {
  601. return subdivide_d;
  602. }
  603. CubeMesh::CubeMesh() {
  604. // defaults
  605. size = Vector3(2.0, 2.0, 2.0);
  606. subdivide_w = default_subdivide_w;
  607. subdivide_h = default_subdivide_h;
  608. subdivide_d = default_subdivide_d;
  609. }
  610. /**
  611. CylinderMesh
  612. */
  613. void CylinderMesh::_create_mesh_array(Array &p_arr) const {
  614. create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings);
  615. }
  616. void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings) {
  617. int i, j, prevrow, thisrow, point;
  618. float x, y, z, u, v, radius;
  619. PoolVector<Vector3> points;
  620. PoolVector<Vector3> normals;
  621. PoolVector<float> tangents;
  622. PoolVector<Vector2> uvs;
  623. PoolVector<int> indices;
  624. point = 0;
  625. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  626. tangents.push_back(m_x); \
  627. tangents.push_back(m_y); \
  628. tangents.push_back(m_z); \
  629. tangents.push_back(m_d);
  630. thisrow = 0;
  631. prevrow = 0;
  632. const real_t side_normal_y = (bottom_radius - top_radius) / height;
  633. for (j = 0; j <= (rings + 1); j++) {
  634. v = j;
  635. v /= (rings + 1);
  636. radius = top_radius + ((bottom_radius - top_radius) * v);
  637. y = height * v;
  638. y = (height * 0.5) - y;
  639. for (i = 0; i <= radial_segments; i++) {
  640. u = i;
  641. u /= radial_segments;
  642. x = sin(u * (Math_PI * 2.0));
  643. z = cos(u * (Math_PI * 2.0));
  644. Vector3 p = Vector3(x * radius, y, z * radius);
  645. points.push_back(p);
  646. normals.push_back(Vector3(x, side_normal_y, z).normalized());
  647. ADD_TANGENT(z, 0.0, -x, 1.0)
  648. uvs.push_back(Vector2(u, v * 0.5));
  649. point++;
  650. if (i > 0 && j > 0) {
  651. indices.push_back(prevrow + i - 1);
  652. indices.push_back(prevrow + i);
  653. indices.push_back(thisrow + i - 1);
  654. indices.push_back(prevrow + i);
  655. indices.push_back(thisrow + i);
  656. indices.push_back(thisrow + i - 1);
  657. };
  658. };
  659. prevrow = thisrow;
  660. thisrow = point;
  661. };
  662. // add top
  663. if (top_radius > 0.0) {
  664. y = height * 0.5;
  665. thisrow = point;
  666. points.push_back(Vector3(0.0, y, 0.0));
  667. normals.push_back(Vector3(0.0, 1.0, 0.0));
  668. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  669. uvs.push_back(Vector2(0.25, 0.75));
  670. point++;
  671. for (i = 0; i <= radial_segments; i++) {
  672. float r = i;
  673. r /= radial_segments;
  674. x = sin(r * (Math_PI * 2.0));
  675. z = cos(r * (Math_PI * 2.0));
  676. u = ((x + 1.0) * 0.25);
  677. v = 0.5 + ((z + 1.0) * 0.25);
  678. Vector3 p = Vector3(x * top_radius, y, z * top_radius);
  679. points.push_back(p);
  680. normals.push_back(Vector3(0.0, 1.0, 0.0));
  681. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  682. uvs.push_back(Vector2(u, v));
  683. point++;
  684. if (i > 0) {
  685. indices.push_back(thisrow);
  686. indices.push_back(point - 1);
  687. indices.push_back(point - 2);
  688. };
  689. };
  690. };
  691. // add bottom
  692. if (bottom_radius > 0.0) {
  693. y = height * -0.5;
  694. thisrow = point;
  695. points.push_back(Vector3(0.0, y, 0.0));
  696. normals.push_back(Vector3(0.0, -1.0, 0.0));
  697. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  698. uvs.push_back(Vector2(0.75, 0.75));
  699. point++;
  700. for (i = 0; i <= radial_segments; i++) {
  701. float r = i;
  702. r /= radial_segments;
  703. x = sin(r * (Math_PI * 2.0));
  704. z = cos(r * (Math_PI * 2.0));
  705. u = 0.5 + ((x + 1.0) * 0.25);
  706. v = 1.0 - ((z + 1.0) * 0.25);
  707. Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
  708. points.push_back(p);
  709. normals.push_back(Vector3(0.0, -1.0, 0.0));
  710. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  711. uvs.push_back(Vector2(u, v));
  712. point++;
  713. if (i > 0) {
  714. indices.push_back(thisrow);
  715. indices.push_back(point - 2);
  716. indices.push_back(point - 1);
  717. };
  718. };
  719. };
  720. p_arr[VS::ARRAY_VERTEX] = points;
  721. p_arr[VS::ARRAY_NORMAL] = normals;
  722. p_arr[VS::ARRAY_TANGENT] = tangents;
  723. p_arr[VS::ARRAY_TEX_UV] = uvs;
  724. p_arr[VS::ARRAY_INDEX] = indices;
  725. }
  726. void CylinderMesh::_bind_methods() {
  727. ClassDB::bind_method(D_METHOD("set_top_radius", "radius"), &CylinderMesh::set_top_radius);
  728. ClassDB::bind_method(D_METHOD("get_top_radius"), &CylinderMesh::get_top_radius);
  729. ClassDB::bind_method(D_METHOD("set_bottom_radius", "radius"), &CylinderMesh::set_bottom_radius);
  730. ClassDB::bind_method(D_METHOD("get_bottom_radius"), &CylinderMesh::get_bottom_radius);
  731. ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderMesh::set_height);
  732. ClassDB::bind_method(D_METHOD("get_height"), &CylinderMesh::get_height);
  733. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CylinderMesh::set_radial_segments);
  734. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CylinderMesh::get_radial_segments);
  735. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings);
  736. ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings);
  737. ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_top_radius", "get_top_radius");
  738. ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_bottom_radius", "get_bottom_radius");
  739. ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater"), "set_height", "get_height");
  740. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  741. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_rings", "get_rings");
  742. }
  743. void CylinderMesh::set_top_radius(const float p_radius) {
  744. top_radius = p_radius;
  745. _request_update();
  746. }
  747. float CylinderMesh::get_top_radius() const {
  748. return top_radius;
  749. }
  750. void CylinderMesh::set_bottom_radius(const float p_radius) {
  751. bottom_radius = p_radius;
  752. _request_update();
  753. }
  754. float CylinderMesh::get_bottom_radius() const {
  755. return bottom_radius;
  756. }
  757. void CylinderMesh::set_height(const float p_height) {
  758. height = p_height;
  759. _request_update();
  760. }
  761. float CylinderMesh::get_height() const {
  762. return height;
  763. }
  764. void CylinderMesh::set_radial_segments(const int p_segments) {
  765. radial_segments = p_segments > 4 ? p_segments : 4;
  766. _request_update();
  767. }
  768. int CylinderMesh::get_radial_segments() const {
  769. return radial_segments;
  770. }
  771. void CylinderMesh::set_rings(const int p_rings) {
  772. rings = p_rings > 0 ? p_rings : 0;
  773. _request_update();
  774. }
  775. int CylinderMesh::get_rings() const {
  776. return rings;
  777. }
  778. CylinderMesh::CylinderMesh() {
  779. // defaults
  780. top_radius = 1.0;
  781. bottom_radius = 1.0;
  782. height = 2.0;
  783. radial_segments = default_radial_segments;
  784. rings = default_rings;
  785. }
  786. /**
  787. PlaneMesh
  788. */
  789. void PlaneMesh::_create_mesh_array(Array &p_arr) const {
  790. int i, j, prevrow, thisrow, point;
  791. float x, z;
  792. Size2 start_pos = size * -0.5;
  793. PoolVector<Vector3> points;
  794. PoolVector<Vector3> normals;
  795. PoolVector<float> tangents;
  796. PoolVector<Vector2> uvs;
  797. PoolVector<int> indices;
  798. point = 0;
  799. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  800. tangents.push_back(m_x); \
  801. tangents.push_back(m_y); \
  802. tangents.push_back(m_z); \
  803. tangents.push_back(m_d);
  804. /* top + bottom */
  805. z = start_pos.y;
  806. thisrow = point;
  807. prevrow = 0;
  808. for (j = 0; j <= (subdivide_d + 1); j++) {
  809. x = start_pos.x;
  810. for (i = 0; i <= (subdivide_w + 1); i++) {
  811. float u = i;
  812. float v = j;
  813. u /= (subdivide_w + 1.0);
  814. v /= (subdivide_d + 1.0);
  815. points.push_back(Vector3(-x, 0.0, -z) + center_offset);
  816. normals.push_back(Vector3(0.0, 1.0, 0.0));
  817. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  818. uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
  819. point++;
  820. if (i > 0 && j > 0) {
  821. indices.push_back(prevrow + i - 1);
  822. indices.push_back(prevrow + i);
  823. indices.push_back(thisrow + i - 1);
  824. indices.push_back(prevrow + i);
  825. indices.push_back(thisrow + i);
  826. indices.push_back(thisrow + i - 1);
  827. };
  828. x += size.x / (subdivide_w + 1.0);
  829. };
  830. z += size.y / (subdivide_d + 1.0);
  831. prevrow = thisrow;
  832. thisrow = point;
  833. };
  834. p_arr[VS::ARRAY_VERTEX] = points;
  835. p_arr[VS::ARRAY_NORMAL] = normals;
  836. p_arr[VS::ARRAY_TANGENT] = tangents;
  837. p_arr[VS::ARRAY_TEX_UV] = uvs;
  838. p_arr[VS::ARRAY_INDEX] = indices;
  839. }
  840. void PlaneMesh::_bind_methods() {
  841. ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaneMesh::set_size);
  842. ClassDB::bind_method(D_METHOD("get_size"), &PlaneMesh::get_size);
  843. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &PlaneMesh::set_subdivide_width);
  844. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
  845. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
  846. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
  847. ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset);
  848. ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset);
  849. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
  850. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  851. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  852. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
  853. }
  854. void PlaneMesh::set_size(const Size2 &p_size) {
  855. size = p_size;
  856. _request_update();
  857. }
  858. Size2 PlaneMesh::get_size() const {
  859. return size;
  860. }
  861. void PlaneMesh::set_subdivide_width(const int p_divisions) {
  862. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  863. _request_update();
  864. }
  865. int PlaneMesh::get_subdivide_width() const {
  866. return subdivide_w;
  867. }
  868. void PlaneMesh::set_subdivide_depth(const int p_divisions) {
  869. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  870. _request_update();
  871. }
  872. int PlaneMesh::get_subdivide_depth() const {
  873. return subdivide_d;
  874. }
  875. void PlaneMesh::set_center_offset(const Vector3 p_offset) {
  876. center_offset = p_offset;
  877. _request_update();
  878. }
  879. Vector3 PlaneMesh::get_center_offset() const {
  880. return center_offset;
  881. }
  882. PlaneMesh::PlaneMesh() {
  883. // defaults
  884. size = Size2(2.0, 2.0);
  885. subdivide_w = 0;
  886. subdivide_d = 0;
  887. center_offset = Vector3(0.0, 0.0, 0.0);
  888. }
  889. /**
  890. PrismMesh
  891. */
  892. void PrismMesh::_create_mesh_array(Array &p_arr) const {
  893. int i, j, prevrow, thisrow, point;
  894. float x, y, z;
  895. float onethird = 1.0 / 3.0;
  896. float twothirds = 2.0 / 3.0;
  897. Vector3 start_pos = size * -0.5;
  898. // set our bounding box
  899. PoolVector<Vector3> points;
  900. PoolVector<Vector3> normals;
  901. PoolVector<float> tangents;
  902. PoolVector<Vector2> uvs;
  903. PoolVector<int> indices;
  904. point = 0;
  905. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  906. tangents.push_back(m_x); \
  907. tangents.push_back(m_y); \
  908. tangents.push_back(m_z); \
  909. tangents.push_back(m_d);
  910. /* front + back */
  911. y = start_pos.y;
  912. thisrow = point;
  913. prevrow = 0;
  914. for (j = 0; j <= (subdivide_h + 1); j++) {
  915. float scale = (y - start_pos.y) / size.y;
  916. float scaled_size_x = size.x * scale;
  917. float start_x = start_pos.x + (1.0 - scale) * size.x * left_to_right;
  918. float offset_front = (1.0 - scale) * onethird * left_to_right;
  919. float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
  920. x = 0.0;
  921. for (i = 0; i <= (subdivide_w + 1); i++) {
  922. float u = i;
  923. float v = j;
  924. u /= (3.0 * (subdivide_w + 1.0));
  925. v /= (2.0 * (subdivide_h + 1.0));
  926. u *= scale;
  927. /* front */
  928. points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
  929. normals.push_back(Vector3(0.0, 0.0, 1.0));
  930. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  931. uvs.push_back(Vector2(offset_front + u, v));
  932. point++;
  933. /* back */
  934. points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
  935. normals.push_back(Vector3(0.0, 0.0, -1.0));
  936. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  937. uvs.push_back(Vector2(twothirds + offset_back + u, v));
  938. point++;
  939. if (i > 0 && j == 1) {
  940. int i2 = i * 2;
  941. /* front */
  942. indices.push_back(prevrow + i2);
  943. indices.push_back(thisrow + i2);
  944. indices.push_back(thisrow + i2 - 2);
  945. /* back */
  946. indices.push_back(prevrow + i2 + 1);
  947. indices.push_back(thisrow + i2 + 1);
  948. indices.push_back(thisrow + i2 - 1);
  949. } else if (i > 0 && j > 0) {
  950. int i2 = i * 2;
  951. /* front */
  952. indices.push_back(prevrow + i2 - 2);
  953. indices.push_back(prevrow + i2);
  954. indices.push_back(thisrow + i2 - 2);
  955. indices.push_back(prevrow + i2);
  956. indices.push_back(thisrow + i2);
  957. indices.push_back(thisrow + i2 - 2);
  958. /* back */
  959. indices.push_back(prevrow + i2 - 1);
  960. indices.push_back(prevrow + i2 + 1);
  961. indices.push_back(thisrow + i2 - 1);
  962. indices.push_back(prevrow + i2 + 1);
  963. indices.push_back(thisrow + i2 + 1);
  964. indices.push_back(thisrow + i2 - 1);
  965. };
  966. x += scale * size.x / (subdivide_w + 1.0);
  967. };
  968. y += size.y / (subdivide_h + 1.0);
  969. prevrow = thisrow;
  970. thisrow = point;
  971. };
  972. /* left + right */
  973. Vector3 normal_left, normal_right;
  974. normal_left = Vector3(-size.y, size.x * left_to_right, 0.0);
  975. normal_right = Vector3(size.y, size.x * (1.0 - left_to_right), 0.0);
  976. normal_left.normalize();
  977. normal_right.normalize();
  978. y = start_pos.y;
  979. thisrow = point;
  980. prevrow = 0;
  981. for (j = 0; j <= (subdivide_h + 1); j++) {
  982. float left, right;
  983. float scale = (y - start_pos.y) / size.y;
  984. left = start_pos.x + (size.x * (1.0 - scale) * left_to_right);
  985. right = left + (size.x * scale);
  986. z = start_pos.z;
  987. for (i = 0; i <= (subdivide_d + 1); i++) {
  988. float u = i;
  989. float v = j;
  990. u /= (3.0 * (subdivide_d + 1.0));
  991. v /= (2.0 * (subdivide_h + 1.0));
  992. /* right */
  993. points.push_back(Vector3(right, -y, -z));
  994. normals.push_back(normal_right);
  995. ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
  996. uvs.push_back(Vector2(onethird + u, v));
  997. point++;
  998. /* left */
  999. points.push_back(Vector3(left, -y, z));
  1000. normals.push_back(normal_left);
  1001. ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
  1002. uvs.push_back(Vector2(u, 0.5 + v));
  1003. point++;
  1004. if (i > 0 && j > 0) {
  1005. int i2 = i * 2;
  1006. /* right */
  1007. indices.push_back(prevrow + i2 - 2);
  1008. indices.push_back(prevrow + i2);
  1009. indices.push_back(thisrow + i2 - 2);
  1010. indices.push_back(prevrow + i2);
  1011. indices.push_back(thisrow + i2);
  1012. indices.push_back(thisrow + i2 - 2);
  1013. /* left */
  1014. indices.push_back(prevrow + i2 - 1);
  1015. indices.push_back(prevrow + i2 + 1);
  1016. indices.push_back(thisrow + i2 - 1);
  1017. indices.push_back(prevrow + i2 + 1);
  1018. indices.push_back(thisrow + i2 + 1);
  1019. indices.push_back(thisrow + i2 - 1);
  1020. };
  1021. z += size.z / (subdivide_d + 1.0);
  1022. };
  1023. y += size.y / (subdivide_h + 1.0);
  1024. prevrow = thisrow;
  1025. thisrow = point;
  1026. };
  1027. /* bottom */
  1028. z = start_pos.z;
  1029. thisrow = point;
  1030. prevrow = 0;
  1031. for (j = 0; j <= (subdivide_d + 1); j++) {
  1032. x = start_pos.x;
  1033. for (i = 0; i <= (subdivide_w + 1); i++) {
  1034. float u = i;
  1035. float v = j;
  1036. u /= (3.0 * (subdivide_w + 1.0));
  1037. v /= (2.0 * (subdivide_d + 1.0));
  1038. /* bottom */
  1039. points.push_back(Vector3(x, start_pos.y, -z));
  1040. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1041. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  1042. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  1043. point++;
  1044. if (i > 0 && j > 0) {
  1045. /* bottom */
  1046. indices.push_back(prevrow + i - 1);
  1047. indices.push_back(prevrow + i);
  1048. indices.push_back(thisrow + i - 1);
  1049. indices.push_back(prevrow + i);
  1050. indices.push_back(thisrow + i);
  1051. indices.push_back(thisrow + i - 1);
  1052. };
  1053. x += size.x / (subdivide_w + 1.0);
  1054. };
  1055. z += size.z / (subdivide_d + 1.0);
  1056. prevrow = thisrow;
  1057. thisrow = point;
  1058. };
  1059. p_arr[VS::ARRAY_VERTEX] = points;
  1060. p_arr[VS::ARRAY_NORMAL] = normals;
  1061. p_arr[VS::ARRAY_TANGENT] = tangents;
  1062. p_arr[VS::ARRAY_TEX_UV] = uvs;
  1063. p_arr[VS::ARRAY_INDEX] = indices;
  1064. }
  1065. void PrismMesh::_bind_methods() {
  1066. ClassDB::bind_method(D_METHOD("set_left_to_right", "left_to_right"), &PrismMesh::set_left_to_right);
  1067. ClassDB::bind_method(D_METHOD("get_left_to_right"), &PrismMesh::get_left_to_right);
  1068. ClassDB::bind_method(D_METHOD("set_size", "size"), &PrismMesh::set_size);
  1069. ClassDB::bind_method(D_METHOD("get_size"), &PrismMesh::get_size);
  1070. ClassDB::bind_method(D_METHOD("set_subdivide_width", "segments"), &PrismMesh::set_subdivide_width);
  1071. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PrismMesh::get_subdivide_width);
  1072. ClassDB::bind_method(D_METHOD("set_subdivide_height", "segments"), &PrismMesh::set_subdivide_height);
  1073. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &PrismMesh::get_subdivide_height);
  1074. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "segments"), &PrismMesh::set_subdivide_depth);
  1075. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth);
  1076. ADD_PROPERTY(PropertyInfo(Variant::REAL, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right");
  1077. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "set_size", "get_size");
  1078. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  1079. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height");
  1080. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  1081. }
  1082. void PrismMesh::set_left_to_right(const float p_left_to_right) {
  1083. left_to_right = p_left_to_right;
  1084. _request_update();
  1085. }
  1086. float PrismMesh::get_left_to_right() const {
  1087. return left_to_right;
  1088. }
  1089. void PrismMesh::set_size(const Vector3 &p_size) {
  1090. size = p_size;
  1091. _request_update();
  1092. }
  1093. Vector3 PrismMesh::get_size() const {
  1094. return size;
  1095. }
  1096. void PrismMesh::set_subdivide_width(const int p_divisions) {
  1097. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  1098. _request_update();
  1099. }
  1100. int PrismMesh::get_subdivide_width() const {
  1101. return subdivide_w;
  1102. }
  1103. void PrismMesh::set_subdivide_height(const int p_divisions) {
  1104. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  1105. _request_update();
  1106. }
  1107. int PrismMesh::get_subdivide_height() const {
  1108. return subdivide_h;
  1109. }
  1110. void PrismMesh::set_subdivide_depth(const int p_divisions) {
  1111. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  1112. _request_update();
  1113. }
  1114. int PrismMesh::get_subdivide_depth() const {
  1115. return subdivide_d;
  1116. }
  1117. PrismMesh::PrismMesh() {
  1118. // defaults
  1119. left_to_right = 0.5;
  1120. size = Vector3(2.0, 2.0, 2.0);
  1121. subdivide_w = 0;
  1122. subdivide_h = 0;
  1123. subdivide_d = 0;
  1124. }
  1125. /**
  1126. QuadMesh
  1127. */
  1128. void QuadMesh::_create_mesh_array(Array &p_arr) const {
  1129. PoolVector<Vector3> faces;
  1130. PoolVector<Vector3> normals;
  1131. PoolVector<float> tangents;
  1132. PoolVector<Vector2> uvs;
  1133. faces.resize(6);
  1134. normals.resize(6);
  1135. tangents.resize(6 * 4);
  1136. uvs.resize(6);
  1137. Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f);
  1138. Vector3 quad_faces[4] = {
  1139. Vector3(-_size.x, -_size.y, 0) + center_offset,
  1140. Vector3(-_size.x, _size.y, 0) + center_offset,
  1141. Vector3(_size.x, _size.y, 0) + center_offset,
  1142. Vector3(_size.x, -_size.y, 0) + center_offset,
  1143. };
  1144. static const int indices[6] = {
  1145. 0, 1, 2,
  1146. 0, 2, 3
  1147. };
  1148. for (int i = 0; i < 6; i++) {
  1149. int j = indices[i];
  1150. faces.set(i, quad_faces[j]);
  1151. normals.set(i, Vector3(0, 0, 1));
  1152. tangents.set(i * 4 + 0, 1.0);
  1153. tangents.set(i * 4 + 1, 0.0);
  1154. tangents.set(i * 4 + 2, 0.0);
  1155. tangents.set(i * 4 + 3, 1.0);
  1156. static const Vector2 quad_uv[4] = {
  1157. Vector2(0, 1),
  1158. Vector2(0, 0),
  1159. Vector2(1, 0),
  1160. Vector2(1, 1),
  1161. };
  1162. uvs.set(i, quad_uv[j]);
  1163. }
  1164. p_arr[VS::ARRAY_VERTEX] = faces;
  1165. p_arr[VS::ARRAY_NORMAL] = normals;
  1166. p_arr[VS::ARRAY_TANGENT] = tangents;
  1167. p_arr[VS::ARRAY_TEX_UV] = uvs;
  1168. }
  1169. void QuadMesh::_bind_methods() {
  1170. ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size);
  1171. ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size);
  1172. ClassDB::bind_method(D_METHOD("set_center_offset", "center_offset"), &QuadMesh::set_center_offset);
  1173. ClassDB::bind_method(D_METHOD("get_center_offset"), &QuadMesh::get_center_offset);
  1174. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
  1175. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset"), "set_center_offset", "get_center_offset");
  1176. }
  1177. QuadMesh::QuadMesh() {
  1178. primitive_type = PRIMITIVE_TRIANGLES;
  1179. size = Size2(1.0, 1.0);
  1180. center_offset = Vector3(0.0, 0.0, 0.0);
  1181. }
  1182. void QuadMesh::set_size(const Size2 &p_size) {
  1183. size = p_size;
  1184. _request_update();
  1185. }
  1186. Size2 QuadMesh::get_size() const {
  1187. return size;
  1188. }
  1189. void QuadMesh::set_center_offset(Vector3 p_center_offset) {
  1190. center_offset = p_center_offset;
  1191. _request_update();
  1192. }
  1193. Vector3 QuadMesh::get_center_offset() const {
  1194. return center_offset;
  1195. }
  1196. /**
  1197. SphereMesh
  1198. */
  1199. void SphereMesh::_create_mesh_array(Array &p_arr) const {
  1200. create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere);
  1201. }
  1202. void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) {
  1203. int i, j, prevrow, thisrow, point;
  1204. float x, y, z;
  1205. float scale = height * (is_hemisphere ? 1.0 : 0.5);
  1206. // set our bounding box
  1207. PoolVector<Vector3> points;
  1208. PoolVector<Vector3> normals;
  1209. PoolVector<float> tangents;
  1210. PoolVector<Vector2> uvs;
  1211. PoolVector<int> indices;
  1212. point = 0;
  1213. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1214. tangents.push_back(m_x); \
  1215. tangents.push_back(m_y); \
  1216. tangents.push_back(m_z); \
  1217. tangents.push_back(m_d);
  1218. thisrow = 0;
  1219. prevrow = 0;
  1220. for (j = 0; j <= (rings + 1); j++) {
  1221. float v = j;
  1222. float w;
  1223. v /= (rings + 1);
  1224. w = sin(Math_PI * v);
  1225. y = scale * cos(Math_PI * v);
  1226. for (i = 0; i <= radial_segments; i++) {
  1227. float u = i;
  1228. u /= radial_segments;
  1229. x = sin(u * (Math_PI * 2.0));
  1230. z = cos(u * (Math_PI * 2.0));
  1231. if (is_hemisphere && y < 0.0) {
  1232. points.push_back(Vector3(x * radius * w, 0.0, z * radius * w));
  1233. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1234. } else {
  1235. Vector3 p = Vector3(x * radius * w, y, z * radius * w);
  1236. points.push_back(p);
  1237. Vector3 normal = Vector3(x * w * scale, radius * (y / scale), z * w * scale);
  1238. normals.push_back(normal.normalized());
  1239. };
  1240. ADD_TANGENT(z, 0.0, -x, 1.0)
  1241. uvs.push_back(Vector2(u, v));
  1242. point++;
  1243. if (i > 0 && j > 0) {
  1244. indices.push_back(prevrow + i - 1);
  1245. indices.push_back(prevrow + i);
  1246. indices.push_back(thisrow + i - 1);
  1247. indices.push_back(prevrow + i);
  1248. indices.push_back(thisrow + i);
  1249. indices.push_back(thisrow + i - 1);
  1250. };
  1251. };
  1252. prevrow = thisrow;
  1253. thisrow = point;
  1254. };
  1255. p_arr[VS::ARRAY_VERTEX] = points;
  1256. p_arr[VS::ARRAY_NORMAL] = normals;
  1257. p_arr[VS::ARRAY_TANGENT] = tangents;
  1258. p_arr[VS::ARRAY_TEX_UV] = uvs;
  1259. p_arr[VS::ARRAY_INDEX] = indices;
  1260. }
  1261. void SphereMesh::_bind_methods() {
  1262. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereMesh::set_radius);
  1263. ClassDB::bind_method(D_METHOD("get_radius"), &SphereMesh::get_radius);
  1264. ClassDB::bind_method(D_METHOD("set_height", "height"), &SphereMesh::set_height);
  1265. ClassDB::bind_method(D_METHOD("get_height"), &SphereMesh::get_height);
  1266. ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &SphereMesh::set_radial_segments);
  1267. ClassDB::bind_method(D_METHOD("get_radial_segments"), &SphereMesh::get_radial_segments);
  1268. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &SphereMesh::set_rings);
  1269. ClassDB::bind_method(D_METHOD("get_rings"), &SphereMesh::get_rings);
  1270. ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere);
  1271. ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere);
  1272. ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius");
  1273. ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height");
  1274. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  1275. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  1276. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere");
  1277. }
  1278. void SphereMesh::set_radius(const float p_radius) {
  1279. radius = p_radius;
  1280. _request_update();
  1281. }
  1282. float SphereMesh::get_radius() const {
  1283. return radius;
  1284. }
  1285. void SphereMesh::set_height(const float p_height) {
  1286. height = p_height;
  1287. _request_update();
  1288. }
  1289. float SphereMesh::get_height() const {
  1290. return height;
  1291. }
  1292. void SphereMesh::set_radial_segments(const int p_radial_segments) {
  1293. radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
  1294. _request_update();
  1295. }
  1296. int SphereMesh::get_radial_segments() const {
  1297. return radial_segments;
  1298. }
  1299. void SphereMesh::set_rings(const int p_rings) {
  1300. rings = p_rings > 1 ? p_rings : 1;
  1301. _request_update();
  1302. }
  1303. int SphereMesh::get_rings() const {
  1304. return rings;
  1305. }
  1306. void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
  1307. is_hemisphere = p_is_hemisphere;
  1308. _request_update();
  1309. }
  1310. bool SphereMesh::get_is_hemisphere() const {
  1311. return is_hemisphere;
  1312. }
  1313. SphereMesh::SphereMesh() {
  1314. // defaults
  1315. radius = 1.0;
  1316. height = 2.0;
  1317. radial_segments = default_radial_segments;
  1318. rings = default_rings;
  1319. is_hemisphere = default_is_hemisphere;
  1320. }
  1321. /**
  1322. PointMesh
  1323. */
  1324. void PointMesh::_create_mesh_array(Array &p_arr) const {
  1325. PoolVector<Vector3> faces;
  1326. faces.resize(1);
  1327. faces.set(0, Vector3(0.0, 0.0, 0.0));
  1328. p_arr[VS::ARRAY_VERTEX] = faces;
  1329. }
  1330. PointMesh::PointMesh() {
  1331. primitive_type = PRIMITIVE_POINTS;
  1332. }
  1333. /**
  1334. TextMesh
  1335. */
  1336. void TextMesh::_generate_glyph_mesh_data(uint32_t p_utf32_char, const Ref<Font> &p_font, CharType p_char, CharType p_next) const {
  1337. if (cache.has(p_utf32_char)) {
  1338. return;
  1339. }
  1340. GlyphMeshData &gl_data = cache[p_utf32_char];
  1341. Dictionary d = p_font->get_char_contours(p_char, p_next);
  1342. PoolVector3Array points = d["points"];
  1343. PoolIntArray contours = d["contours"];
  1344. bool orientation = d["orientation"];
  1345. if (points.size() < 3 || contours.size() < 1) {
  1346. return; // No full contours, only glyph control points (or nothing), ignore.
  1347. }
  1348. // Approximate Bezier curves as polygons.
  1349. // See https://freetype.org/freetype2/docs/glyphs/glyphs-6.html, for more info.
  1350. for (int i = 0; i < contours.size(); i++) {
  1351. int32_t start = (i == 0) ? 0 : (contours[i - 1] + 1);
  1352. int32_t end = contours[i];
  1353. Vector<ContourPoint> polygon;
  1354. for (int32_t j = start; j <= end; j++) {
  1355. if (points[j].z == Font::CONTOUR_CURVE_TAG_ON) {
  1356. // Point on the curve.
  1357. Vector2 p = Vector2(points[j].x, points[j].y) * pixel_size;
  1358. polygon.push_back(ContourPoint(p, true));
  1359. } else if (points[j].z == Font::CONTOUR_CURVE_TAG_OFF_CONIC) {
  1360. // Conic Bezier arc.
  1361. int32_t next = (j == end) ? start : (j + 1);
  1362. int32_t prev = (j == start) ? end : (j - 1);
  1363. Vector2 p0;
  1364. Vector2 p1 = Vector2(points[j].x, points[j].y);
  1365. Vector2 p2;
  1366. // For successive conic OFF points add a virtual ON point in the middle.
  1367. if (points[prev].z == Font::CONTOUR_CURVE_TAG_OFF_CONIC) {
  1368. p0 = (Vector2(points[prev].x, points[prev].y) + Vector2(points[j].x, points[j].y)) / 2.0;
  1369. } else if (points[prev].z == Font::CONTOUR_CURVE_TAG_ON) {
  1370. p0 = Vector2(points[prev].x, points[prev].y);
  1371. } else {
  1372. ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j));
  1373. }
  1374. if (points[next].z == Font::CONTOUR_CURVE_TAG_OFF_CONIC) {
  1375. p2 = (Vector2(points[j].x, points[j].y) + Vector2(points[next].x, points[next].y)) / 2.0;
  1376. } else if (points[next].z == Font::CONTOUR_CURVE_TAG_ON) {
  1377. p2 = Vector2(points[next].x, points[next].y);
  1378. } else {
  1379. ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j));
  1380. }
  1381. real_t step = CLAMP(curve_step / (p0 - p2).length(), 0.01, 0.5);
  1382. real_t t = step;
  1383. while (t < 1.0) {
  1384. real_t omt = (1.0 - t);
  1385. real_t omt2 = omt * omt;
  1386. real_t t2 = t * t;
  1387. Vector2 point = p1 + omt2 * (p0 - p1) + t2 * (p2 - p1);
  1388. Vector2 p = point * pixel_size;
  1389. polygon.push_back(ContourPoint(p, false));
  1390. t += step;
  1391. }
  1392. } else if (points[j].z == Font::CONTOUR_CURVE_TAG_OFF_CUBIC) {
  1393. // Cubic Bezier arc.
  1394. int32_t cur = j;
  1395. int32_t next1 = (j == end) ? start : (j + 1);
  1396. int32_t next2 = (next1 == end) ? start : (next1 + 1);
  1397. int32_t prev = (j == start) ? end : (j - 1);
  1398. // There must be exactly two OFF points and two ON points for each cubic arc.
  1399. if (points[prev].z != Font::CONTOUR_CURVE_TAG_ON) {
  1400. cur = (cur == 0) ? end : cur - 1;
  1401. next1 = (next1 == 0) ? end : next1 - 1;
  1402. next2 = (next2 == 0) ? end : next2 - 1;
  1403. prev = (prev == 0) ? end : prev - 1;
  1404. } else {
  1405. j++;
  1406. }
  1407. ERR_FAIL_COND_MSG(points[prev].z != Font::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, prev));
  1408. ERR_FAIL_COND_MSG(points[cur].z != Font::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, cur));
  1409. ERR_FAIL_COND_MSG(points[next1].z != Font::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, next1));
  1410. ERR_FAIL_COND_MSG(points[next2].z != Font::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, next2));
  1411. Vector2 p0 = Vector2(points[prev].x, points[prev].y);
  1412. Vector2 p1 = Vector2(points[cur].x, points[cur].y);
  1413. Vector2 p2 = Vector2(points[next1].x, points[next1].y);
  1414. Vector2 p3 = Vector2(points[next2].x, points[next2].y);
  1415. real_t step = CLAMP(curve_step / (p0 - p3).length(), 0.01, 0.5);
  1416. real_t t = step;
  1417. while (t < 1.0) {
  1418. real_t omt = (1.0 - t);
  1419. real_t omt2 = omt * omt;
  1420. real_t omt3 = omt2 * omt;
  1421. real_t t2 = t * t;
  1422. real_t t3 = t2 * t;
  1423. Vector2 point = p0 * omt3 + p1 * omt2 * t * 3.0 + p2 * omt * t2 * 3.0 + p3 * t3;
  1424. Vector2 p = point * pixel_size;
  1425. polygon.push_back(ContourPoint(p, false));
  1426. t += step;
  1427. }
  1428. } else {
  1429. ERR_FAIL_MSG(vformat("Unknown point tag at %d:%d", i, j));
  1430. }
  1431. }
  1432. if (polygon.size() < 3) {
  1433. continue; // Skip glyph control points.
  1434. }
  1435. if (!orientation) {
  1436. polygon.invert();
  1437. }
  1438. gl_data.contours.push_back(polygon);
  1439. }
  1440. // Calculate bounds.
  1441. List<TriangulatorPoly> in_poly;
  1442. for (int i = 0; i < gl_data.contours.size(); i++) {
  1443. TriangulatorPoly inp;
  1444. inp.Init(gl_data.contours[i].size());
  1445. real_t length = 0.0;
  1446. for (int j = 0; j < gl_data.contours[i].size(); j++) {
  1447. int next = (j + 1 == gl_data.contours[i].size()) ? 0 : (j + 1);
  1448. gl_data.min_p.x = MIN(gl_data.min_p.x, gl_data.contours[i][j].point.x);
  1449. gl_data.min_p.y = MIN(gl_data.min_p.y, gl_data.contours[i][j].point.y);
  1450. gl_data.max_p.x = MAX(gl_data.max_p.x, gl_data.contours[i][j].point.x);
  1451. gl_data.max_p.y = MAX(gl_data.max_p.y, gl_data.contours[i][j].point.y);
  1452. length += (gl_data.contours[i][next].point - gl_data.contours[i][j].point).length();
  1453. inp.GetPoint(j) = gl_data.contours[i][j].point;
  1454. }
  1455. int poly_orient = inp.GetOrientation();
  1456. if (poly_orient == TRIANGULATOR_CW) {
  1457. inp.SetHole(true);
  1458. }
  1459. in_poly.push_back(inp);
  1460. gl_data.contours_info.push_back(ContourInfo(length, poly_orient == TRIANGULATOR_CCW));
  1461. }
  1462. TriangulatorPartition tpart;
  1463. //Decompose and triangulate.
  1464. List<TriangulatorPoly> out_poly;
  1465. if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) {
  1466. ERR_FAIL_MSG("Convex decomposing failed. Make sure the font doesn't contain self-intersecting lines, as these are not supported in TextMesh.");
  1467. }
  1468. List<TriangulatorPoly> out_tris;
  1469. for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) {
  1470. if (tpart.Triangulate_OPT(&(I->get()), &out_tris) == 0) {
  1471. ERR_FAIL_MSG("Triangulation failed. Make sure the font doesn't contain self-intersecting lines, as these are not supported in TextMesh.");
  1472. }
  1473. }
  1474. for (List<TriangulatorPoly>::Element *I = out_tris.front(); I; I = I->next()) {
  1475. TriangulatorPoly &tp = I->get();
  1476. ERR_FAIL_COND(tp.GetNumPoints() != 3); // Triangles only.
  1477. for (int i = 0; i < 3; i++) {
  1478. gl_data.triangles.push_back(Vector2(tp.GetPoint(i).x, tp.GetPoint(i).y));
  1479. }
  1480. }
  1481. }
  1482. void TextMesh::_create_mesh_array(Array &p_arr) const {
  1483. Ref<Font> font = _get_font_or_default();
  1484. ERR_FAIL_COND(font.is_null());
  1485. if (dirty_cache) {
  1486. cache.clear();
  1487. dirty_cache = false;
  1488. }
  1489. String t = (uppercase) ? xl_text.to_upper() : xl_text;
  1490. float line_width = font->get_string_size(t).x * pixel_size;
  1491. Vector2 offset;
  1492. switch (horizontal_alignment) {
  1493. case ALIGN_LEFT:
  1494. offset.x = 0.0;
  1495. break;
  1496. case ALIGN_CENTER: {
  1497. offset.x = -line_width / 2.0;
  1498. } break;
  1499. case ALIGN_RIGHT: {
  1500. offset.x = -line_width;
  1501. } break;
  1502. }
  1503. bool has_depth = !Math::is_zero_approx(depth);
  1504. // Generate glyph data, precalculate size of the arrays and mesh bounds for UV.
  1505. int64_t p_size = 0;
  1506. int64_t i_size = 0;
  1507. Vector2 min_p = Vector2(INFINITY, INFINITY);
  1508. Vector2 max_p = Vector2(-INFINITY, -INFINITY);
  1509. Vector2 offset_pre = offset;
  1510. for (int i = 0; i < t.size(); i++) {
  1511. CharType c = t[i];
  1512. CharType n = t[i + 1];
  1513. uint32_t utf32_char = c;
  1514. if (((c & 0xfffffc00) == 0xd800) && (n & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
  1515. utf32_char = (c << 10UL) + n - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
  1516. }
  1517. if ((c & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
  1518. continue;
  1519. }
  1520. if (utf32_char >= 0x20) {
  1521. _generate_glyph_mesh_data(utf32_char, font, c, n);
  1522. GlyphMeshData &gl_data = cache[utf32_char];
  1523. p_size += gl_data.triangles.size() * ((has_depth) ? 2 : 1);
  1524. i_size += gl_data.triangles.size() * ((has_depth) ? 2 : 1);
  1525. if (has_depth) {
  1526. for (int j = 0; j < gl_data.contours.size(); j++) {
  1527. p_size += gl_data.contours[j].size() * 4;
  1528. i_size += gl_data.contours[j].size() * 6;
  1529. }
  1530. }
  1531. min_p.x = MIN(gl_data.min_p.x + offset_pre.x, min_p.x);
  1532. min_p.y = MIN(gl_data.min_p.y + offset_pre.y, min_p.y);
  1533. max_p.x = MAX(gl_data.max_p.x + offset_pre.x, max_p.x);
  1534. max_p.y = MAX(gl_data.max_p.y + offset_pre.y, max_p.y);
  1535. }
  1536. offset_pre.x += font->get_char_size(c, n).x * pixel_size;
  1537. }
  1538. PoolVector<Vector3> vertices;
  1539. PoolVector<Vector3> normals;
  1540. PoolVector<float> tangents;
  1541. PoolVector<Vector2> uvs;
  1542. PoolVector<int> indices;
  1543. vertices.resize(p_size);
  1544. normals.resize(p_size);
  1545. uvs.resize(p_size);
  1546. tangents.resize(p_size * 4);
  1547. indices.resize(i_size);
  1548. PoolVector<Vector3>::Write vertices_ptr = vertices.write();
  1549. PoolVector<Vector3>::Write normals_ptr = normals.write();
  1550. PoolVector<float>::Write tangents_ptr = tangents.write();
  1551. PoolVector<Vector2>::Write uvs_ptr = uvs.write();
  1552. PoolVector<int>::Write indices_ptr = indices.write();
  1553. // Generate mesh.
  1554. int32_t p_idx = 0;
  1555. int32_t i_idx = 0;
  1556. for (int i = 0; i < t.size(); i++) {
  1557. CharType c = t[i];
  1558. CharType n = t[i + 1];
  1559. uint32_t utf32_char = c;
  1560. if (((c & 0xfffffc00) == 0xd800) && (n & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
  1561. utf32_char = (c << 10UL) + n - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
  1562. }
  1563. if ((c & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
  1564. continue;
  1565. }
  1566. if (utf32_char >= 0x20) {
  1567. _generate_glyph_mesh_data(utf32_char, font, c, n);
  1568. GlyphMeshData &gl_data = cache[utf32_char];
  1569. int64_t ts = gl_data.triangles.size();
  1570. const Vector2 *ts_ptr = gl_data.triangles.ptr();
  1571. for (int k = 0; k < ts; k += 3) {
  1572. // Add front face.
  1573. for (int l = 0; l < 3; l++) {
  1574. Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0);
  1575. vertices_ptr[p_idx] = point;
  1576. normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0);
  1577. if (has_depth) {
  1578. uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4)));
  1579. } else {
  1580. uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0)));
  1581. }
  1582. tangents_ptr[p_idx * 4 + 0] = 1.0;
  1583. tangents_ptr[p_idx * 4 + 1] = 0.0;
  1584. tangents_ptr[p_idx * 4 + 2] = 0.0;
  1585. tangents_ptr[p_idx * 4 + 3] = 1.0;
  1586. indices_ptr[i_idx++] = p_idx;
  1587. p_idx++;
  1588. }
  1589. if (has_depth) {
  1590. // Add back face.
  1591. for (int l = 2; l >= 0; l--) {
  1592. Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0);
  1593. vertices_ptr[p_idx] = point;
  1594. normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0);
  1595. uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.4), real_t(0.8)));
  1596. tangents_ptr[p_idx * 4 + 0] = -1.0;
  1597. tangents_ptr[p_idx * 4 + 1] = 0.0;
  1598. tangents_ptr[p_idx * 4 + 2] = 0.0;
  1599. tangents_ptr[p_idx * 4 + 3] = 1.0;
  1600. indices_ptr[i_idx++] = p_idx;
  1601. p_idx++;
  1602. }
  1603. }
  1604. }
  1605. // Add sides.
  1606. if (has_depth) {
  1607. for (int k = 0; k < gl_data.contours.size(); k++) {
  1608. int64_t ps = gl_data.contours[k].size();
  1609. const ContourPoint *ps_ptr = gl_data.contours[k].ptr();
  1610. const ContourInfo &ps_info = gl_data.contours_info[k];
  1611. real_t length = 0.0;
  1612. for (int l = 0; l < ps; l++) {
  1613. int prev = (l == 0) ? (ps - 1) : (l - 1);
  1614. int next = (l + 1 == ps) ? 0 : (l + 1);
  1615. Vector2 d1;
  1616. Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized();
  1617. if (ps_ptr[l].sharp) {
  1618. d1 = d2;
  1619. } else {
  1620. d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized();
  1621. }
  1622. real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length();
  1623. Vector3 quad_faces[4] = {
  1624. Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0),
  1625. Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0),
  1626. Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0),
  1627. Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0),
  1628. };
  1629. for (int m = 0; m < 4; m++) {
  1630. const Vector2 &d = ((m % 2) == 0) ? d1 : d2;
  1631. real_t u_pos = ((m % 2) == 0) ? length : length + seg_len;
  1632. vertices_ptr[p_idx + m] = quad_faces[m];
  1633. normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0);
  1634. if (m < 2) {
  1635. uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9);
  1636. } else {
  1637. uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0);
  1638. }
  1639. tangents_ptr[(p_idx + m) * 4 + 0] = d.x;
  1640. tangents_ptr[(p_idx + m) * 4 + 1] = -d.y;
  1641. tangents_ptr[(p_idx + m) * 4 + 2] = 0.0;
  1642. tangents_ptr[(p_idx + m) * 4 + 3] = 1.0;
  1643. }
  1644. indices_ptr[i_idx++] = p_idx;
  1645. indices_ptr[i_idx++] = p_idx + 1;
  1646. indices_ptr[i_idx++] = p_idx + 2;
  1647. indices_ptr[i_idx++] = p_idx + 1;
  1648. indices_ptr[i_idx++] = p_idx + 3;
  1649. indices_ptr[i_idx++] = p_idx + 2;
  1650. length += seg_len;
  1651. p_idx += 4;
  1652. }
  1653. }
  1654. }
  1655. }
  1656. offset.x += font->get_char_size(c, n).x * pixel_size;
  1657. }
  1658. if (p_size == 0) {
  1659. // If empty, add single triangle to suppress errors.
  1660. vertices.push_back(Vector3());
  1661. normals.push_back(Vector3());
  1662. uvs.push_back(Vector2());
  1663. tangents.push_back(1.0);
  1664. tangents.push_back(0.0);
  1665. tangents.push_back(0.0);
  1666. tangents.push_back(1.0);
  1667. indices.push_back(0);
  1668. indices.push_back(0);
  1669. indices.push_back(0);
  1670. }
  1671. p_arr[VS::ARRAY_VERTEX] = vertices;
  1672. p_arr[VS::ARRAY_NORMAL] = normals;
  1673. p_arr[VS::ARRAY_TANGENT] = tangents;
  1674. p_arr[VS::ARRAY_TEX_UV] = uvs;
  1675. p_arr[VS::ARRAY_INDEX] = indices;
  1676. }
  1677. void TextMesh::_bind_methods() {
  1678. ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &TextMesh::set_horizontal_alignment);
  1679. ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &TextMesh::get_horizontal_alignment);
  1680. ClassDB::bind_method(D_METHOD("set_text", "text"), &TextMesh::set_text);
  1681. ClassDB::bind_method(D_METHOD("get_text"), &TextMesh::get_text);
  1682. ClassDB::bind_method(D_METHOD("set_font", "font"), &TextMesh::set_font);
  1683. ClassDB::bind_method(D_METHOD("get_font"), &TextMesh::get_font);
  1684. ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth);
  1685. ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth);
  1686. ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &TextMesh::set_pixel_size);
  1687. ClassDB::bind_method(D_METHOD("get_pixel_size"), &TextMesh::get_pixel_size);
  1688. ClassDB::bind_method(D_METHOD("set_curve_step", "curve_step"), &TextMesh::set_curve_step);
  1689. ClassDB::bind_method(D_METHOD("get_curve_step"), &TextMesh::get_curve_step);
  1690. ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &TextMesh::set_uppercase);
  1691. ClassDB::bind_method(D_METHOD("is_uppercase"), &TextMesh::is_uppercase);
  1692. ClassDB::bind_method(D_METHOD("_font_changed"), &TextMesh::_font_changed);
  1693. ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update);
  1694. ADD_GROUP("Text", "");
  1695. ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
  1696. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
  1697. ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_horizontal_alignment", "get_horizontal_alignment");
  1698. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
  1699. ADD_GROUP("Mesh", "");
  1700. ADD_PROPERTY(PropertyInfo(Variant::REAL, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
  1701. ADD_PROPERTY(PropertyInfo(Variant::REAL, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "set_curve_step", "get_curve_step");
  1702. ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater"), "set_depth", "get_depth");
  1703. BIND_ENUM_CONSTANT(ALIGN_LEFT);
  1704. BIND_ENUM_CONSTANT(ALIGN_CENTER);
  1705. BIND_ENUM_CONSTANT(ALIGN_RIGHT);
  1706. }
  1707. void TextMesh::_notification(int p_what) {
  1708. switch (p_what) {
  1709. case MainLoop::NOTIFICATION_TRANSLATION_CHANGED: {
  1710. String new_text = tr(text);
  1711. if (new_text == xl_text) {
  1712. return; // Nothing new.
  1713. }
  1714. xl_text = new_text;
  1715. _request_update();
  1716. } break;
  1717. }
  1718. }
  1719. TextMesh::TextMesh() {
  1720. primitive_type = PRIMITIVE_TRIANGLES;
  1721. }
  1722. TextMesh::~TextMesh() {
  1723. }
  1724. void TextMesh::set_horizontal_alignment(TextMesh::Align p_alignment) {
  1725. ERR_FAIL_INDEX((int)p_alignment, 3);
  1726. if (horizontal_alignment != p_alignment) {
  1727. horizontal_alignment = p_alignment;
  1728. _request_update();
  1729. }
  1730. }
  1731. TextMesh::Align TextMesh::get_horizontal_alignment() const {
  1732. return horizontal_alignment;
  1733. }
  1734. void TextMesh::set_text(const String &p_string) {
  1735. if (text != p_string) {
  1736. text = p_string;
  1737. xl_text = tr(text);
  1738. _request_update();
  1739. }
  1740. }
  1741. String TextMesh::get_text() const {
  1742. return text;
  1743. }
  1744. void TextMesh::_font_changed() {
  1745. dirty_cache = true;
  1746. call_deferred("_request_update");
  1747. }
  1748. void TextMesh::set_font(const Ref<Font> &p_font) {
  1749. if (font_override != p_font) {
  1750. if (font_override.is_valid()) {
  1751. font_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_font_changed");
  1752. }
  1753. font_override = p_font;
  1754. dirty_cache = true;
  1755. if (font_override.is_valid()) {
  1756. font_override->connect(CoreStringNames::get_singleton()->changed, this, "_font_changed");
  1757. }
  1758. _request_update();
  1759. }
  1760. }
  1761. Ref<Font> TextMesh::get_font() const {
  1762. return font_override;
  1763. }
  1764. Ref<Font> TextMesh::_get_font_or_default() const {
  1765. if (font_override.is_valid()) {
  1766. return font_override;
  1767. }
  1768. // Check the project-defined Theme resource.
  1769. if (Theme::get_project_default().is_valid()) {
  1770. List<StringName> theme_types;
  1771. Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
  1772. for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
  1773. if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E->get())) {
  1774. return Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E->get());
  1775. }
  1776. }
  1777. }
  1778. // Lastly, fall back on the items defined in the default Theme, if they exist.
  1779. {
  1780. List<StringName> theme_types;
  1781. Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
  1782. for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
  1783. if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E->get())) {
  1784. return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E->get());
  1785. }
  1786. }
  1787. }
  1788. // If they don't exist, use any type to return the default/empty value.
  1789. return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
  1790. }
  1791. void TextMesh::set_depth(real_t p_depth) {
  1792. if (depth != p_depth) {
  1793. depth = MAX(p_depth, 0.0);
  1794. _request_update();
  1795. }
  1796. }
  1797. real_t TextMesh::get_depth() const {
  1798. return depth;
  1799. }
  1800. void TextMesh::set_pixel_size(real_t p_amount) {
  1801. if (pixel_size != p_amount) {
  1802. pixel_size = CLAMP(p_amount, 0.0001, 128.0);
  1803. dirty_cache = true;
  1804. _request_update();
  1805. }
  1806. }
  1807. real_t TextMesh::get_pixel_size() const {
  1808. return pixel_size;
  1809. }
  1810. void TextMesh::set_curve_step(real_t p_step) {
  1811. if (curve_step != p_step) {
  1812. curve_step = CLAMP(p_step, 0.1, 10.0);
  1813. dirty_cache = true;
  1814. _request_update();
  1815. }
  1816. }
  1817. real_t TextMesh::get_curve_step() const {
  1818. return curve_step;
  1819. }
  1820. void TextMesh::set_uppercase(bool p_uppercase) {
  1821. if (uppercase != p_uppercase) {
  1822. uppercase = p_uppercase;
  1823. _request_update();
  1824. }
  1825. }
  1826. bool TextMesh::is_uppercase() const {
  1827. return uppercase;
  1828. }