primitive_meshes.cpp 96 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168
  1. /*************************************************************************/
  2. /* primitive_meshes.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 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 "primitive_meshes.h"
  31. #include "core/core_string_names.h"
  32. #include "scene/resources/theme.h"
  33. #include "scene/theme/theme_db.h"
  34. #include "servers/rendering_server.h"
  35. #include "thirdparty/misc/clipper.hpp"
  36. #include "thirdparty/misc/polypartition.h"
  37. /**
  38. PrimitiveMesh
  39. */
  40. void PrimitiveMesh::_update() const {
  41. Array arr;
  42. if (GDVIRTUAL_CALL(_create_mesh_array, arr)) {
  43. ERR_FAIL_COND_MSG(arr.size() != RS::ARRAY_MAX, "_create_mesh_array must return an array of Mesh.ARRAY_MAX elements.");
  44. } else {
  45. arr.resize(RS::ARRAY_MAX);
  46. _create_mesh_array(arr);
  47. }
  48. Vector<Vector3> points = arr[RS::ARRAY_VERTEX];
  49. ERR_FAIL_COND_MSG(points.size() == 0, "_create_mesh_array must return at least a vertex array.");
  50. aabb = AABB();
  51. int pc = points.size();
  52. ERR_FAIL_COND(pc == 0);
  53. {
  54. const Vector3 *r = points.ptr();
  55. for (int i = 0; i < pc; i++) {
  56. if (i == 0) {
  57. aabb.position = r[i];
  58. } else {
  59. aabb.expand_to(r[i]);
  60. }
  61. }
  62. }
  63. Vector<int> indices = arr[RS::ARRAY_INDEX];
  64. if (flip_faces) {
  65. Vector<Vector3> normals = arr[RS::ARRAY_NORMAL];
  66. if (normals.size() && indices.size()) {
  67. {
  68. int nc = normals.size();
  69. Vector3 *w = normals.ptrw();
  70. for (int i = 0; i < nc; i++) {
  71. w[i] = -w[i];
  72. }
  73. }
  74. {
  75. int ic = indices.size();
  76. int *w = indices.ptrw();
  77. for (int i = 0; i < ic; i += 3) {
  78. SWAP(w[i + 0], w[i + 1]);
  79. }
  80. }
  81. arr[RS::ARRAY_NORMAL] = normals;
  82. arr[RS::ARRAY_INDEX] = indices;
  83. }
  84. }
  85. array_len = pc;
  86. index_array_len = indices.size();
  87. // in with the new
  88. RenderingServer::get_singleton()->mesh_clear(mesh);
  89. RenderingServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (RenderingServer::PrimitiveType)primitive_type, arr);
  90. RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  91. pending_request = false;
  92. clear_cache();
  93. const_cast<PrimitiveMesh *>(this)->emit_changed();
  94. }
  95. void PrimitiveMesh::_request_update() {
  96. if (pending_request) {
  97. return;
  98. }
  99. _update();
  100. }
  101. int PrimitiveMesh::get_surface_count() const {
  102. if (pending_request) {
  103. _update();
  104. }
  105. return 1;
  106. }
  107. int PrimitiveMesh::surface_get_array_len(int p_idx) const {
  108. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  109. if (pending_request) {
  110. _update();
  111. }
  112. return array_len;
  113. }
  114. int PrimitiveMesh::surface_get_array_index_len(int p_idx) const {
  115. ERR_FAIL_INDEX_V(p_idx, 1, -1);
  116. if (pending_request) {
  117. _update();
  118. }
  119. return index_array_len;
  120. }
  121. Array PrimitiveMesh::surface_get_arrays(int p_surface) const {
  122. ERR_FAIL_INDEX_V(p_surface, 1, Array());
  123. if (pending_request) {
  124. _update();
  125. }
  126. return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, 0);
  127. }
  128. Dictionary PrimitiveMesh::surface_get_lods(int p_surface) const {
  129. return Dictionary(); //not really supported
  130. }
  131. TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const {
  132. return TypedArray<Array>(); //not really supported
  133. }
  134. uint32_t PrimitiveMesh::surface_get_format(int p_idx) const {
  135. ERR_FAIL_INDEX_V(p_idx, 1, 0);
  136. return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX;
  137. }
  138. Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const {
  139. return primitive_type;
  140. }
  141. void PrimitiveMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
  142. ERR_FAIL_INDEX(p_idx, 1);
  143. set_material(p_material);
  144. }
  145. Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const {
  146. ERR_FAIL_INDEX_V(p_idx, 1, nullptr);
  147. return material;
  148. }
  149. int PrimitiveMesh::get_blend_shape_count() const {
  150. return 0;
  151. }
  152. StringName PrimitiveMesh::get_blend_shape_name(int p_index) const {
  153. return StringName();
  154. }
  155. void PrimitiveMesh::set_blend_shape_name(int p_index, const StringName &p_name) {
  156. }
  157. AABB PrimitiveMesh::get_aabb() const {
  158. if (pending_request) {
  159. _update();
  160. }
  161. return aabb;
  162. }
  163. RID PrimitiveMesh::get_rid() const {
  164. if (pending_request) {
  165. _update();
  166. }
  167. return mesh;
  168. }
  169. void PrimitiveMesh::_bind_methods() {
  170. ClassDB::bind_method(D_METHOD("_update"), &PrimitiveMesh::_update);
  171. ClassDB::bind_method(D_METHOD("set_material", "material"), &PrimitiveMesh::set_material);
  172. ClassDB::bind_method(D_METHOD("get_material"), &PrimitiveMesh::get_material);
  173. ClassDB::bind_method(D_METHOD("get_mesh_arrays"), &PrimitiveMesh::get_mesh_arrays);
  174. ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &PrimitiveMesh::set_custom_aabb);
  175. ClassDB::bind_method(D_METHOD("get_custom_aabb"), &PrimitiveMesh::get_custom_aabb);
  176. ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces);
  177. ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces);
  178. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
  179. ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
  180. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
  181. GDVIRTUAL_BIND(_create_mesh_array);
  182. }
  183. void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
  184. material = p_material;
  185. if (!pending_request) {
  186. // just apply it, else it'll happen when _update is called.
  187. RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid());
  188. notify_property_list_changed();
  189. emit_changed();
  190. };
  191. }
  192. Ref<Material> PrimitiveMesh::get_material() const {
  193. return material;
  194. }
  195. Array PrimitiveMesh::get_mesh_arrays() const {
  196. return surface_get_arrays(0);
  197. }
  198. void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) {
  199. custom_aabb = p_custom;
  200. RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
  201. emit_changed();
  202. }
  203. AABB PrimitiveMesh::get_custom_aabb() const {
  204. return custom_aabb;
  205. }
  206. void PrimitiveMesh::set_flip_faces(bool p_enable) {
  207. flip_faces = p_enable;
  208. _request_update();
  209. }
  210. bool PrimitiveMesh::get_flip_faces() const {
  211. return flip_faces;
  212. }
  213. PrimitiveMesh::PrimitiveMesh() {
  214. mesh = RenderingServer::get_singleton()->mesh_create();
  215. }
  216. PrimitiveMesh::~PrimitiveMesh() {
  217. RenderingServer::get_singleton()->free(mesh);
  218. }
  219. /**
  220. CapsuleMesh
  221. */
  222. void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
  223. create_mesh_array(p_arr, radius, height, radial_segments, rings);
  224. }
  225. void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings) {
  226. int i, j, prevrow, thisrow, point;
  227. float x, y, z, u, v, w;
  228. float onethird = 1.0 / 3.0;
  229. float twothirds = 2.0 / 3.0;
  230. // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom
  231. Vector<Vector3> points;
  232. Vector<Vector3> normals;
  233. Vector<float> tangents;
  234. Vector<Vector2> uvs;
  235. Vector<int> indices;
  236. point = 0;
  237. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  238. tangents.push_back(m_x); \
  239. tangents.push_back(m_y); \
  240. tangents.push_back(m_z); \
  241. tangents.push_back(m_d);
  242. /* top hemisphere */
  243. thisrow = 0;
  244. prevrow = 0;
  245. for (j = 0; j <= (rings + 1); j++) {
  246. v = j;
  247. v /= (rings + 1);
  248. w = sin(0.5 * Math_PI * v);
  249. y = radius * cos(0.5 * Math_PI * v);
  250. for (i = 0; i <= radial_segments; i++) {
  251. u = i;
  252. u /= radial_segments;
  253. x = -sin(u * Math_TAU);
  254. z = cos(u * Math_TAU);
  255. Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
  256. points.push_back(p + Vector3(0.0, 0.5 * height - radius, 0.0));
  257. normals.push_back(p.normalized());
  258. ADD_TANGENT(-z, 0.0, -x, 1.0)
  259. uvs.push_back(Vector2(u, v * onethird));
  260. point++;
  261. if (i > 0 && j > 0) {
  262. indices.push_back(prevrow + i - 1);
  263. indices.push_back(prevrow + i);
  264. indices.push_back(thisrow + i - 1);
  265. indices.push_back(prevrow + i);
  266. indices.push_back(thisrow + i);
  267. indices.push_back(thisrow + i - 1);
  268. };
  269. };
  270. prevrow = thisrow;
  271. thisrow = point;
  272. };
  273. /* cylinder */
  274. thisrow = point;
  275. prevrow = 0;
  276. for (j = 0; j <= (rings + 1); j++) {
  277. v = j;
  278. v /= (rings + 1);
  279. y = (height - 2.0 * radius) * v;
  280. y = (0.5 * height - radius) - y;
  281. for (i = 0; i <= radial_segments; i++) {
  282. u = i;
  283. u /= radial_segments;
  284. x = -sin(u * Math_TAU);
  285. z = cos(u * Math_TAU);
  286. Vector3 p = Vector3(x * radius, y, -z * radius);
  287. points.push_back(p);
  288. normals.push_back(Vector3(x, 0.0, -z));
  289. ADD_TANGENT(-z, 0.0, -x, 1.0)
  290. uvs.push_back(Vector2(u, onethird + (v * onethird)));
  291. point++;
  292. if (i > 0 && j > 0) {
  293. indices.push_back(prevrow + i - 1);
  294. indices.push_back(prevrow + i);
  295. indices.push_back(thisrow + i - 1);
  296. indices.push_back(prevrow + i);
  297. indices.push_back(thisrow + i);
  298. indices.push_back(thisrow + i - 1);
  299. };
  300. };
  301. prevrow = thisrow;
  302. thisrow = point;
  303. };
  304. /* bottom hemisphere */
  305. thisrow = point;
  306. prevrow = 0;
  307. for (j = 0; j <= (rings + 1); j++) {
  308. v = j;
  309. v /= (rings + 1);
  310. v += 1.0;
  311. w = sin(0.5 * Math_PI * v);
  312. y = radius * cos(0.5 * Math_PI * v);
  313. for (i = 0; i <= radial_segments; i++) {
  314. float u2 = i;
  315. u2 /= radial_segments;
  316. x = -sin(u2 * Math_TAU);
  317. z = cos(u2 * Math_TAU);
  318. Vector3 p = Vector3(x * radius * w, y, -z * radius * w);
  319. points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0));
  320. normals.push_back(p.normalized());
  321. ADD_TANGENT(-z, 0.0, -x, 1.0)
  322. uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird)));
  323. point++;
  324. if (i > 0 && j > 0) {
  325. indices.push_back(prevrow + i - 1);
  326. indices.push_back(prevrow + i);
  327. indices.push_back(thisrow + i - 1);
  328. indices.push_back(prevrow + i);
  329. indices.push_back(thisrow + i);
  330. indices.push_back(thisrow + i - 1);
  331. };
  332. };
  333. prevrow = thisrow;
  334. thisrow = point;
  335. };
  336. p_arr[RS::ARRAY_VERTEX] = points;
  337. p_arr[RS::ARRAY_NORMAL] = normals;
  338. p_arr[RS::ARRAY_TANGENT] = tangents;
  339. p_arr[RS::ARRAY_TEX_UV] = uvs;
  340. p_arr[RS::ARRAY_INDEX] = indices;
  341. }
  342. void CapsuleMesh::_bind_methods() {
  343. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleMesh::set_radius);
  344. ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleMesh::get_radius);
  345. ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleMesh::set_height);
  346. ClassDB::bind_method(D_METHOD("get_height"), &CapsuleMesh::get_height);
  347. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CapsuleMesh::set_radial_segments);
  348. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CapsuleMesh::get_radial_segments);
  349. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings);
  350. ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings);
  351. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
  352. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_height", "get_height");
  353. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  354. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  355. ADD_LINKED_PROPERTY("radius", "height");
  356. ADD_LINKED_PROPERTY("height", "radius");
  357. }
  358. void CapsuleMesh::set_radius(const float p_radius) {
  359. radius = p_radius;
  360. if (radius > height * 0.5) {
  361. height = radius * 2.0;
  362. }
  363. _request_update();
  364. }
  365. float CapsuleMesh::get_radius() const {
  366. return radius;
  367. }
  368. void CapsuleMesh::set_height(const float p_height) {
  369. height = p_height;
  370. if (radius > height * 0.5) {
  371. radius = height * 0.5;
  372. }
  373. _request_update();
  374. }
  375. float CapsuleMesh::get_height() const {
  376. return height;
  377. }
  378. void CapsuleMesh::set_radial_segments(const int p_segments) {
  379. radial_segments = p_segments > 4 ? p_segments : 4;
  380. _request_update();
  381. }
  382. int CapsuleMesh::get_radial_segments() const {
  383. return radial_segments;
  384. }
  385. void CapsuleMesh::set_rings(const int p_rings) {
  386. rings = p_rings > 1 ? p_rings : 1;
  387. _request_update();
  388. }
  389. int CapsuleMesh::get_rings() const {
  390. return rings;
  391. }
  392. CapsuleMesh::CapsuleMesh() {}
  393. /**
  394. BoxMesh
  395. */
  396. void BoxMesh::_create_mesh_array(Array &p_arr) const {
  397. BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d);
  398. }
  399. void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, 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. Vector<Vector3> points;
  407. Vector<Vector3> normals;
  408. Vector<float> tangents;
  409. Vector<Vector2> uvs;
  410. Vector<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[RS::ARRAY_VERTEX] = points;
  556. p_arr[RS::ARRAY_NORMAL] = normals;
  557. p_arr[RS::ARRAY_TANGENT] = tangents;
  558. p_arr[RS::ARRAY_TEX_UV] = uvs;
  559. p_arr[RS::ARRAY_INDEX] = indices;
  560. }
  561. void BoxMesh::_bind_methods() {
  562. ClassDB::bind_method(D_METHOD("set_size", "size"), &BoxMesh::set_size);
  563. ClassDB::bind_method(D_METHOD("get_size"), &BoxMesh::get_size);
  564. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &BoxMesh::set_subdivide_width);
  565. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &BoxMesh::get_subdivide_width);
  566. ClassDB::bind_method(D_METHOD("set_subdivide_height", "divisions"), &BoxMesh::set_subdivide_height);
  567. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &BoxMesh::get_subdivide_height);
  568. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "divisions"), &BoxMesh::set_subdivide_depth);
  569. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &BoxMesh::get_subdivide_depth);
  570. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "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 BoxMesh::set_size(const Vector3 &p_size) {
  576. size = p_size;
  577. _request_update();
  578. }
  579. Vector3 BoxMesh::get_size() const {
  580. return size;
  581. }
  582. void BoxMesh::set_subdivide_width(const int p_divisions) {
  583. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  584. _request_update();
  585. }
  586. int BoxMesh::get_subdivide_width() const {
  587. return subdivide_w;
  588. }
  589. void BoxMesh::set_subdivide_height(const int p_divisions) {
  590. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  591. _request_update();
  592. }
  593. int BoxMesh::get_subdivide_height() const {
  594. return subdivide_h;
  595. }
  596. void BoxMesh::set_subdivide_depth(const int p_divisions) {
  597. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  598. _request_update();
  599. }
  600. int BoxMesh::get_subdivide_depth() const {
  601. return subdivide_d;
  602. }
  603. BoxMesh::BoxMesh() {}
  604. /**
  605. CylinderMesh
  606. */
  607. void CylinderMesh::_create_mesh_array(Array &p_arr) const {
  608. create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings, cap_top, cap_bottom);
  609. }
  610. void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings, bool cap_top, bool cap_bottom) {
  611. int i, j, prevrow, thisrow, point;
  612. float x, y, z, u, v, radius;
  613. Vector<Vector3> points;
  614. Vector<Vector3> normals;
  615. Vector<float> tangents;
  616. Vector<Vector2> uvs;
  617. Vector<int> indices;
  618. point = 0;
  619. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  620. tangents.push_back(m_x); \
  621. tangents.push_back(m_y); \
  622. tangents.push_back(m_z); \
  623. tangents.push_back(m_d);
  624. thisrow = 0;
  625. prevrow = 0;
  626. for (j = 0; j <= (rings + 1); j++) {
  627. v = j;
  628. v /= (rings + 1);
  629. radius = top_radius + ((bottom_radius - top_radius) * v);
  630. y = height * v;
  631. y = (height * 0.5) - y;
  632. for (i = 0; i <= radial_segments; i++) {
  633. u = i;
  634. u /= radial_segments;
  635. x = sin(u * Math_TAU);
  636. z = cos(u * Math_TAU);
  637. Vector3 p = Vector3(x * radius, y, z * radius);
  638. points.push_back(p);
  639. normals.push_back(Vector3(x, 0.0, z));
  640. ADD_TANGENT(z, 0.0, -x, 1.0)
  641. uvs.push_back(Vector2(u, v * 0.5));
  642. point++;
  643. if (i > 0 && j > 0) {
  644. indices.push_back(prevrow + i - 1);
  645. indices.push_back(prevrow + i);
  646. indices.push_back(thisrow + i - 1);
  647. indices.push_back(prevrow + i);
  648. indices.push_back(thisrow + i);
  649. indices.push_back(thisrow + i - 1);
  650. };
  651. };
  652. prevrow = thisrow;
  653. thisrow = point;
  654. };
  655. // add top
  656. if (cap_top && top_radius > 0.0) {
  657. y = height * 0.5;
  658. thisrow = point;
  659. points.push_back(Vector3(0.0, y, 0.0));
  660. normals.push_back(Vector3(0.0, 1.0, 0.0));
  661. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  662. uvs.push_back(Vector2(0.25, 0.75));
  663. point++;
  664. for (i = 0; i <= radial_segments; i++) {
  665. float r = i;
  666. r /= radial_segments;
  667. x = sin(r * Math_TAU);
  668. z = cos(r * Math_TAU);
  669. u = ((x + 1.0) * 0.25);
  670. v = 0.5 + ((z + 1.0) * 0.25);
  671. Vector3 p = Vector3(x * top_radius, y, z * top_radius);
  672. points.push_back(p);
  673. normals.push_back(Vector3(0.0, 1.0, 0.0));
  674. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  675. uvs.push_back(Vector2(u, v));
  676. point++;
  677. if (i > 0) {
  678. indices.push_back(thisrow);
  679. indices.push_back(point - 1);
  680. indices.push_back(point - 2);
  681. };
  682. };
  683. };
  684. // add bottom
  685. if (cap_bottom && bottom_radius > 0.0) {
  686. y = height * -0.5;
  687. thisrow = point;
  688. points.push_back(Vector3(0.0, y, 0.0));
  689. normals.push_back(Vector3(0.0, -1.0, 0.0));
  690. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  691. uvs.push_back(Vector2(0.75, 0.75));
  692. point++;
  693. for (i = 0; i <= radial_segments; i++) {
  694. float r = i;
  695. r /= radial_segments;
  696. x = sin(r * Math_TAU);
  697. z = cos(r * Math_TAU);
  698. u = 0.5 + ((x + 1.0) * 0.25);
  699. v = 1.0 - ((z + 1.0) * 0.25);
  700. Vector3 p = Vector3(x * bottom_radius, y, z * bottom_radius);
  701. points.push_back(p);
  702. normals.push_back(Vector3(0.0, -1.0, 0.0));
  703. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  704. uvs.push_back(Vector2(u, v));
  705. point++;
  706. if (i > 0) {
  707. indices.push_back(thisrow);
  708. indices.push_back(point - 2);
  709. indices.push_back(point - 1);
  710. };
  711. };
  712. };
  713. p_arr[RS::ARRAY_VERTEX] = points;
  714. p_arr[RS::ARRAY_NORMAL] = normals;
  715. p_arr[RS::ARRAY_TANGENT] = tangents;
  716. p_arr[RS::ARRAY_TEX_UV] = uvs;
  717. p_arr[RS::ARRAY_INDEX] = indices;
  718. }
  719. void CylinderMesh::_bind_methods() {
  720. ClassDB::bind_method(D_METHOD("set_top_radius", "radius"), &CylinderMesh::set_top_radius);
  721. ClassDB::bind_method(D_METHOD("get_top_radius"), &CylinderMesh::get_top_radius);
  722. ClassDB::bind_method(D_METHOD("set_bottom_radius", "radius"), &CylinderMesh::set_bottom_radius);
  723. ClassDB::bind_method(D_METHOD("get_bottom_radius"), &CylinderMesh::get_bottom_radius);
  724. ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderMesh::set_height);
  725. ClassDB::bind_method(D_METHOD("get_height"), &CylinderMesh::get_height);
  726. ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CylinderMesh::set_radial_segments);
  727. ClassDB::bind_method(D_METHOD("get_radial_segments"), &CylinderMesh::get_radial_segments);
  728. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings);
  729. ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings);
  730. ClassDB::bind_method(D_METHOD("set_cap_top", "cap_top"), &CylinderMesh::set_cap_top);
  731. ClassDB::bind_method(D_METHOD("is_cap_top"), &CylinderMesh::is_cap_top);
  732. ClassDB::bind_method(D_METHOD("set_cap_bottom", "cap_bottom"), &CylinderMesh::set_cap_bottom);
  733. ClassDB::bind_method(D_METHOD("is_cap_bottom"), &CylinderMesh::is_cap_bottom);
  734. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "top_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater,suffix:m"), "set_top_radius", "get_top_radius");
  735. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bottom_radius", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater,suffix:m"), "set_bottom_radius", "get_bottom_radius");
  736. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater,suffix:m"), "set_height", "get_height");
  737. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  738. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  739. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_top"), "set_cap_top", "is_cap_top");
  740. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_bottom"), "set_cap_bottom", "is_cap_bottom");
  741. }
  742. void CylinderMesh::set_top_radius(const float p_radius) {
  743. top_radius = p_radius;
  744. _request_update();
  745. }
  746. float CylinderMesh::get_top_radius() const {
  747. return top_radius;
  748. }
  749. void CylinderMesh::set_bottom_radius(const float p_radius) {
  750. bottom_radius = p_radius;
  751. _request_update();
  752. }
  753. float CylinderMesh::get_bottom_radius() const {
  754. return bottom_radius;
  755. }
  756. void CylinderMesh::set_height(const float p_height) {
  757. height = p_height;
  758. _request_update();
  759. }
  760. float CylinderMesh::get_height() const {
  761. return height;
  762. }
  763. void CylinderMesh::set_radial_segments(const int p_segments) {
  764. radial_segments = p_segments > 4 ? p_segments : 4;
  765. _request_update();
  766. }
  767. int CylinderMesh::get_radial_segments() const {
  768. return radial_segments;
  769. }
  770. void CylinderMesh::set_rings(const int p_rings) {
  771. rings = p_rings > 0 ? p_rings : 0;
  772. _request_update();
  773. }
  774. int CylinderMesh::get_rings() const {
  775. return rings;
  776. }
  777. void CylinderMesh::set_cap_top(bool p_cap_top) {
  778. cap_top = p_cap_top;
  779. _request_update();
  780. }
  781. bool CylinderMesh::is_cap_top() const {
  782. return cap_top;
  783. }
  784. void CylinderMesh::set_cap_bottom(bool p_cap_bottom) {
  785. cap_bottom = p_cap_bottom;
  786. _request_update();
  787. }
  788. bool CylinderMesh::is_cap_bottom() const {
  789. return cap_bottom;
  790. }
  791. CylinderMesh::CylinderMesh() {}
  792. /**
  793. PlaneMesh
  794. */
  795. void PlaneMesh::_create_mesh_array(Array &p_arr) const {
  796. int i, j, prevrow, thisrow, point;
  797. float x, z;
  798. Size2 start_pos = size * -0.5;
  799. Vector3 normal = Vector3(0.0, 1.0, 0.0);
  800. if (orientation == FACE_X) {
  801. normal = Vector3(1.0, 0.0, 0.0);
  802. } else if (orientation == FACE_Z) {
  803. normal = Vector3(0.0, 0.0, 1.0);
  804. }
  805. Vector<Vector3> points;
  806. Vector<Vector3> normals;
  807. Vector<float> tangents;
  808. Vector<Vector2> uvs;
  809. Vector<int> indices;
  810. point = 0;
  811. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  812. tangents.push_back(m_x); \
  813. tangents.push_back(m_y); \
  814. tangents.push_back(m_z); \
  815. tangents.push_back(m_d);
  816. /* top + bottom */
  817. z = start_pos.y;
  818. thisrow = point;
  819. prevrow = 0;
  820. for (j = 0; j <= (subdivide_d + 1); j++) {
  821. x = start_pos.x;
  822. for (i = 0; i <= (subdivide_w + 1); i++) {
  823. float u = i;
  824. float v = j;
  825. u /= (subdivide_w + 1.0);
  826. v /= (subdivide_d + 1.0);
  827. if (orientation == FACE_X) {
  828. points.push_back(Vector3(0.0, z, x) + center_offset);
  829. } else if (orientation == FACE_Y) {
  830. points.push_back(Vector3(-x, 0.0, -z) + center_offset);
  831. } else if (orientation == FACE_Z) {
  832. points.push_back(Vector3(-x, z, 0.0) + center_offset);
  833. }
  834. normals.push_back(normal);
  835. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  836. uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */
  837. point++;
  838. if (i > 0 && j > 0) {
  839. indices.push_back(prevrow + i - 1);
  840. indices.push_back(prevrow + i);
  841. indices.push_back(thisrow + i - 1);
  842. indices.push_back(prevrow + i);
  843. indices.push_back(thisrow + i);
  844. indices.push_back(thisrow + i - 1);
  845. };
  846. x += size.x / (subdivide_w + 1.0);
  847. };
  848. z += size.y / (subdivide_d + 1.0);
  849. prevrow = thisrow;
  850. thisrow = point;
  851. };
  852. p_arr[RS::ARRAY_VERTEX] = points;
  853. p_arr[RS::ARRAY_NORMAL] = normals;
  854. p_arr[RS::ARRAY_TANGENT] = tangents;
  855. p_arr[RS::ARRAY_TEX_UV] = uvs;
  856. p_arr[RS::ARRAY_INDEX] = indices;
  857. }
  858. void PlaneMesh::_bind_methods() {
  859. ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaneMesh::set_size);
  860. ClassDB::bind_method(D_METHOD("get_size"), &PlaneMesh::get_size);
  861. ClassDB::bind_method(D_METHOD("set_subdivide_width", "subdivide"), &PlaneMesh::set_subdivide_width);
  862. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width);
  863. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth);
  864. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth);
  865. ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset);
  866. ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset);
  867. ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &PlaneMesh::set_orientation);
  868. ClassDB::bind_method(D_METHOD("get_orientation"), &PlaneMesh::get_orientation);
  869. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
  870. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  871. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  872. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset");
  873. ADD_PROPERTY(PropertyInfo(Variant::INT, "orientation", PROPERTY_HINT_ENUM, "Face X, Face Y, Face Z"), "set_orientation", "get_orientation");
  874. BIND_ENUM_CONSTANT(FACE_X)
  875. BIND_ENUM_CONSTANT(FACE_Y)
  876. BIND_ENUM_CONSTANT(FACE_Z)
  877. }
  878. void PlaneMesh::set_size(const Size2 &p_size) {
  879. size = p_size;
  880. _request_update();
  881. }
  882. Size2 PlaneMesh::get_size() const {
  883. return size;
  884. }
  885. void PlaneMesh::set_subdivide_width(const int p_divisions) {
  886. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  887. _request_update();
  888. }
  889. int PlaneMesh::get_subdivide_width() const {
  890. return subdivide_w;
  891. }
  892. void PlaneMesh::set_subdivide_depth(const int p_divisions) {
  893. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  894. _request_update();
  895. }
  896. int PlaneMesh::get_subdivide_depth() const {
  897. return subdivide_d;
  898. }
  899. void PlaneMesh::set_center_offset(const Vector3 p_offset) {
  900. center_offset = p_offset;
  901. _request_update();
  902. }
  903. Vector3 PlaneMesh::get_center_offset() const {
  904. return center_offset;
  905. }
  906. void PlaneMesh::set_orientation(const Orientation p_orientation) {
  907. orientation = p_orientation;
  908. _request_update();
  909. }
  910. PlaneMesh::Orientation PlaneMesh::get_orientation() const {
  911. return orientation;
  912. }
  913. PlaneMesh::PlaneMesh() {}
  914. /**
  915. PrismMesh
  916. */
  917. void PrismMesh::_create_mesh_array(Array &p_arr) const {
  918. int i, j, prevrow, thisrow, point;
  919. float x, y, z;
  920. float onethird = 1.0 / 3.0;
  921. float twothirds = 2.0 / 3.0;
  922. Vector3 start_pos = size * -0.5;
  923. // set our bounding box
  924. Vector<Vector3> points;
  925. Vector<Vector3> normals;
  926. Vector<float> tangents;
  927. Vector<Vector2> uvs;
  928. Vector<int> indices;
  929. point = 0;
  930. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  931. tangents.push_back(m_x); \
  932. tangents.push_back(m_y); \
  933. tangents.push_back(m_z); \
  934. tangents.push_back(m_d);
  935. /* front + back */
  936. y = start_pos.y;
  937. thisrow = point;
  938. prevrow = 0;
  939. for (j = 0; j <= (subdivide_h + 1); j++) {
  940. float scale = (y - start_pos.y) / size.y;
  941. float scaled_size_x = size.x * scale;
  942. float start_x = start_pos.x + (1.0 - scale) * size.x * left_to_right;
  943. float offset_front = (1.0 - scale) * onethird * left_to_right;
  944. float offset_back = (1.0 - scale) * onethird * (1.0 - left_to_right);
  945. x = 0.0;
  946. for (i = 0; i <= (subdivide_w + 1); i++) {
  947. float u = i;
  948. float v = j;
  949. u /= (3.0 * (subdivide_w + 1.0));
  950. v /= (2.0 * (subdivide_h + 1.0));
  951. u *= scale;
  952. /* front */
  953. points.push_back(Vector3(start_x + x, -y, -start_pos.z)); // double negative on the Z!
  954. normals.push_back(Vector3(0.0, 0.0, 1.0));
  955. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  956. uvs.push_back(Vector2(offset_front + u, v));
  957. point++;
  958. /* back */
  959. points.push_back(Vector3(start_x + scaled_size_x - x, -y, start_pos.z));
  960. normals.push_back(Vector3(0.0, 0.0, -1.0));
  961. ADD_TANGENT(-1.0, 0.0, 0.0, 1.0);
  962. uvs.push_back(Vector2(twothirds + offset_back + u, v));
  963. point++;
  964. if (i > 0 && j == 1) {
  965. int i2 = i * 2;
  966. /* front */
  967. indices.push_back(prevrow + i2);
  968. indices.push_back(thisrow + i2);
  969. indices.push_back(thisrow + i2 - 2);
  970. /* back */
  971. indices.push_back(prevrow + i2 + 1);
  972. indices.push_back(thisrow + i2 + 1);
  973. indices.push_back(thisrow + i2 - 1);
  974. } else if (i > 0 && j > 0) {
  975. int i2 = i * 2;
  976. /* front */
  977. indices.push_back(prevrow + i2 - 2);
  978. indices.push_back(prevrow + i2);
  979. indices.push_back(thisrow + i2 - 2);
  980. indices.push_back(prevrow + i2);
  981. indices.push_back(thisrow + i2);
  982. indices.push_back(thisrow + i2 - 2);
  983. /* back */
  984. indices.push_back(prevrow + i2 - 1);
  985. indices.push_back(prevrow + i2 + 1);
  986. indices.push_back(thisrow + i2 - 1);
  987. indices.push_back(prevrow + i2 + 1);
  988. indices.push_back(thisrow + i2 + 1);
  989. indices.push_back(thisrow + i2 - 1);
  990. };
  991. x += scale * size.x / (subdivide_w + 1.0);
  992. };
  993. y += size.y / (subdivide_h + 1.0);
  994. prevrow = thisrow;
  995. thisrow = point;
  996. };
  997. /* left + right */
  998. Vector3 normal_left, normal_right;
  999. normal_left = Vector3(-size.y, size.x * left_to_right, 0.0);
  1000. normal_right = Vector3(size.y, size.x * (1.0 - left_to_right), 0.0);
  1001. normal_left.normalize();
  1002. normal_right.normalize();
  1003. y = start_pos.y;
  1004. thisrow = point;
  1005. prevrow = 0;
  1006. for (j = 0; j <= (subdivide_h + 1); j++) {
  1007. float left, right;
  1008. float scale = (y - start_pos.y) / size.y;
  1009. left = start_pos.x + (size.x * (1.0 - scale) * left_to_right);
  1010. right = left + (size.x * scale);
  1011. z = start_pos.z;
  1012. for (i = 0; i <= (subdivide_d + 1); i++) {
  1013. float u = i;
  1014. float v = j;
  1015. u /= (3.0 * (subdivide_d + 1.0));
  1016. v /= (2.0 * (subdivide_h + 1.0));
  1017. /* right */
  1018. points.push_back(Vector3(right, -y, -z));
  1019. normals.push_back(normal_right);
  1020. ADD_TANGENT(0.0, 0.0, -1.0, 1.0);
  1021. uvs.push_back(Vector2(onethird + u, v));
  1022. point++;
  1023. /* left */
  1024. points.push_back(Vector3(left, -y, z));
  1025. normals.push_back(normal_left);
  1026. ADD_TANGENT(0.0, 0.0, 1.0, 1.0);
  1027. uvs.push_back(Vector2(u, 0.5 + v));
  1028. point++;
  1029. if (i > 0 && j > 0) {
  1030. int i2 = i * 2;
  1031. /* right */
  1032. indices.push_back(prevrow + i2 - 2);
  1033. indices.push_back(prevrow + i2);
  1034. indices.push_back(thisrow + i2 - 2);
  1035. indices.push_back(prevrow + i2);
  1036. indices.push_back(thisrow + i2);
  1037. indices.push_back(thisrow + i2 - 2);
  1038. /* left */
  1039. indices.push_back(prevrow + i2 - 1);
  1040. indices.push_back(prevrow + i2 + 1);
  1041. indices.push_back(thisrow + i2 - 1);
  1042. indices.push_back(prevrow + i2 + 1);
  1043. indices.push_back(thisrow + i2 + 1);
  1044. indices.push_back(thisrow + i2 - 1);
  1045. };
  1046. z += size.z / (subdivide_d + 1.0);
  1047. };
  1048. y += size.y / (subdivide_h + 1.0);
  1049. prevrow = thisrow;
  1050. thisrow = point;
  1051. };
  1052. /* bottom */
  1053. z = start_pos.z;
  1054. thisrow = point;
  1055. prevrow = 0;
  1056. for (j = 0; j <= (subdivide_d + 1); j++) {
  1057. x = start_pos.x;
  1058. for (i = 0; i <= (subdivide_w + 1); i++) {
  1059. float u = i;
  1060. float v = j;
  1061. u /= (3.0 * (subdivide_w + 1.0));
  1062. v /= (2.0 * (subdivide_d + 1.0));
  1063. /* bottom */
  1064. points.push_back(Vector3(x, start_pos.y, -z));
  1065. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1066. ADD_TANGENT(1.0, 0.0, 0.0, 1.0);
  1067. uvs.push_back(Vector2(twothirds + u, 0.5 + v));
  1068. point++;
  1069. if (i > 0 && j > 0) {
  1070. /* bottom */
  1071. indices.push_back(prevrow + i - 1);
  1072. indices.push_back(prevrow + i);
  1073. indices.push_back(thisrow + i - 1);
  1074. indices.push_back(prevrow + i);
  1075. indices.push_back(thisrow + i);
  1076. indices.push_back(thisrow + i - 1);
  1077. };
  1078. x += size.x / (subdivide_w + 1.0);
  1079. };
  1080. z += size.z / (subdivide_d + 1.0);
  1081. prevrow = thisrow;
  1082. thisrow = point;
  1083. };
  1084. p_arr[RS::ARRAY_VERTEX] = points;
  1085. p_arr[RS::ARRAY_NORMAL] = normals;
  1086. p_arr[RS::ARRAY_TANGENT] = tangents;
  1087. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1088. p_arr[RS::ARRAY_INDEX] = indices;
  1089. }
  1090. void PrismMesh::_bind_methods() {
  1091. ClassDB::bind_method(D_METHOD("set_left_to_right", "left_to_right"), &PrismMesh::set_left_to_right);
  1092. ClassDB::bind_method(D_METHOD("get_left_to_right"), &PrismMesh::get_left_to_right);
  1093. ClassDB::bind_method(D_METHOD("set_size", "size"), &PrismMesh::set_size);
  1094. ClassDB::bind_method(D_METHOD("get_size"), &PrismMesh::get_size);
  1095. ClassDB::bind_method(D_METHOD("set_subdivide_width", "segments"), &PrismMesh::set_subdivide_width);
  1096. ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PrismMesh::get_subdivide_width);
  1097. ClassDB::bind_method(D_METHOD("set_subdivide_height", "segments"), &PrismMesh::set_subdivide_height);
  1098. ClassDB::bind_method(D_METHOD("get_subdivide_height"), &PrismMesh::get_subdivide_height);
  1099. ClassDB::bind_method(D_METHOD("set_subdivide_depth", "segments"), &PrismMesh::set_subdivide_depth);
  1100. ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth);
  1101. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right");
  1102. ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size");
  1103. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width");
  1104. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height");
  1105. ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth");
  1106. }
  1107. void PrismMesh::set_left_to_right(const float p_left_to_right) {
  1108. left_to_right = p_left_to_right;
  1109. _request_update();
  1110. }
  1111. float PrismMesh::get_left_to_right() const {
  1112. return left_to_right;
  1113. }
  1114. void PrismMesh::set_size(const Vector3 &p_size) {
  1115. size = p_size;
  1116. _request_update();
  1117. }
  1118. Vector3 PrismMesh::get_size() const {
  1119. return size;
  1120. }
  1121. void PrismMesh::set_subdivide_width(const int p_divisions) {
  1122. subdivide_w = p_divisions > 0 ? p_divisions : 0;
  1123. _request_update();
  1124. }
  1125. int PrismMesh::get_subdivide_width() const {
  1126. return subdivide_w;
  1127. }
  1128. void PrismMesh::set_subdivide_height(const int p_divisions) {
  1129. subdivide_h = p_divisions > 0 ? p_divisions : 0;
  1130. _request_update();
  1131. }
  1132. int PrismMesh::get_subdivide_height() const {
  1133. return subdivide_h;
  1134. }
  1135. void PrismMesh::set_subdivide_depth(const int p_divisions) {
  1136. subdivide_d = p_divisions > 0 ? p_divisions : 0;
  1137. _request_update();
  1138. }
  1139. int PrismMesh::get_subdivide_depth() const {
  1140. return subdivide_d;
  1141. }
  1142. PrismMesh::PrismMesh() {}
  1143. /**
  1144. SphereMesh
  1145. */
  1146. void SphereMesh::_create_mesh_array(Array &p_arr) const {
  1147. create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere);
  1148. }
  1149. void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) {
  1150. int i, j, prevrow, thisrow, point;
  1151. float x, y, z;
  1152. float scale = height * (is_hemisphere ? 1.0 : 0.5);
  1153. // set our bounding box
  1154. Vector<Vector3> points;
  1155. Vector<Vector3> normals;
  1156. Vector<float> tangents;
  1157. Vector<Vector2> uvs;
  1158. Vector<int> indices;
  1159. point = 0;
  1160. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1161. tangents.push_back(m_x); \
  1162. tangents.push_back(m_y); \
  1163. tangents.push_back(m_z); \
  1164. tangents.push_back(m_d);
  1165. thisrow = 0;
  1166. prevrow = 0;
  1167. for (j = 0; j <= (rings + 1); j++) {
  1168. float v = j;
  1169. float w;
  1170. v /= (rings + 1);
  1171. w = sin(Math_PI * v);
  1172. y = scale * cos(Math_PI * v);
  1173. for (i = 0; i <= radial_segments; i++) {
  1174. float u = i;
  1175. u /= radial_segments;
  1176. x = sin(u * Math_TAU);
  1177. z = cos(u * Math_TAU);
  1178. if (is_hemisphere && y < 0.0) {
  1179. points.push_back(Vector3(x * radius * w, 0.0, z * radius * w));
  1180. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1181. } else {
  1182. Vector3 p = Vector3(x * radius * w, y, z * radius * w);
  1183. points.push_back(p);
  1184. Vector3 normal = Vector3(x * w * scale, radius * (y / scale), z * w * scale);
  1185. normals.push_back(normal.normalized());
  1186. };
  1187. ADD_TANGENT(z, 0.0, -x, 1.0)
  1188. uvs.push_back(Vector2(u, v));
  1189. point++;
  1190. if (i > 0 && j > 0) {
  1191. indices.push_back(prevrow + i - 1);
  1192. indices.push_back(prevrow + i);
  1193. indices.push_back(thisrow + i - 1);
  1194. indices.push_back(prevrow + i);
  1195. indices.push_back(thisrow + i);
  1196. indices.push_back(thisrow + i - 1);
  1197. };
  1198. };
  1199. prevrow = thisrow;
  1200. thisrow = point;
  1201. };
  1202. p_arr[RS::ARRAY_VERTEX] = points;
  1203. p_arr[RS::ARRAY_NORMAL] = normals;
  1204. p_arr[RS::ARRAY_TANGENT] = tangents;
  1205. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1206. p_arr[RS::ARRAY_INDEX] = indices;
  1207. }
  1208. void SphereMesh::_bind_methods() {
  1209. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereMesh::set_radius);
  1210. ClassDB::bind_method(D_METHOD("get_radius"), &SphereMesh::get_radius);
  1211. ClassDB::bind_method(D_METHOD("set_height", "height"), &SphereMesh::set_height);
  1212. ClassDB::bind_method(D_METHOD("get_height"), &SphereMesh::get_height);
  1213. ClassDB::bind_method(D_METHOD("set_radial_segments", "radial_segments"), &SphereMesh::set_radial_segments);
  1214. ClassDB::bind_method(D_METHOD("get_radial_segments"), &SphereMesh::get_radial_segments);
  1215. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &SphereMesh::set_rings);
  1216. ClassDB::bind_method(D_METHOD("get_rings"), &SphereMesh::get_rings);
  1217. ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere);
  1218. ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere);
  1219. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
  1220. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_height", "get_height");
  1221. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments");
  1222. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings");
  1223. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere");
  1224. }
  1225. void SphereMesh::set_radius(const float p_radius) {
  1226. radius = p_radius;
  1227. _request_update();
  1228. }
  1229. float SphereMesh::get_radius() const {
  1230. return radius;
  1231. }
  1232. void SphereMesh::set_height(const float p_height) {
  1233. height = p_height;
  1234. _request_update();
  1235. }
  1236. float SphereMesh::get_height() const {
  1237. return height;
  1238. }
  1239. void SphereMesh::set_radial_segments(const int p_radial_segments) {
  1240. radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
  1241. _request_update();
  1242. }
  1243. int SphereMesh::get_radial_segments() const {
  1244. return radial_segments;
  1245. }
  1246. void SphereMesh::set_rings(const int p_rings) {
  1247. rings = p_rings > 1 ? p_rings : 1;
  1248. _request_update();
  1249. }
  1250. int SphereMesh::get_rings() const {
  1251. return rings;
  1252. }
  1253. void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) {
  1254. is_hemisphere = p_is_hemisphere;
  1255. _request_update();
  1256. }
  1257. bool SphereMesh::get_is_hemisphere() const {
  1258. return is_hemisphere;
  1259. }
  1260. SphereMesh::SphereMesh() {}
  1261. /**
  1262. TorusMesh
  1263. */
  1264. void TorusMesh::_create_mesh_array(Array &p_arr) const {
  1265. // set our bounding box
  1266. Vector<Vector3> points;
  1267. Vector<Vector3> normals;
  1268. Vector<float> tangents;
  1269. Vector<Vector2> uvs;
  1270. Vector<int> indices;
  1271. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1272. tangents.push_back(m_x); \
  1273. tangents.push_back(m_y); \
  1274. tangents.push_back(m_z); \
  1275. tangents.push_back(m_d);
  1276. ERR_FAIL_COND_MSG(inner_radius == outer_radius, "Inner radius and outer radius cannot be the same.");
  1277. float min_radius = inner_radius;
  1278. float max_radius = outer_radius;
  1279. if (min_radius > max_radius) {
  1280. SWAP(min_radius, max_radius);
  1281. }
  1282. float radius = (max_radius - min_radius) * 0.5;
  1283. for (int i = 0; i <= rings; i++) {
  1284. int prevrow = (i - 1) * (ring_segments + 1);
  1285. int thisrow = i * (ring_segments + 1);
  1286. float inci = float(i) / rings;
  1287. float angi = inci * Math_TAU;
  1288. Vector2 normali = Vector2(-Math::sin(angi), -Math::cos(angi));
  1289. for (int j = 0; j <= ring_segments; j++) {
  1290. float incj = float(j) / ring_segments;
  1291. float angj = incj * Math_TAU;
  1292. Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj));
  1293. Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0);
  1294. points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x));
  1295. normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x));
  1296. ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0);
  1297. uvs.push_back(Vector2(inci, incj));
  1298. if (i > 0 && j > 0) {
  1299. indices.push_back(thisrow + j - 1);
  1300. indices.push_back(prevrow + j);
  1301. indices.push_back(prevrow + j - 1);
  1302. indices.push_back(thisrow + j - 1);
  1303. indices.push_back(thisrow + j);
  1304. indices.push_back(prevrow + j);
  1305. }
  1306. }
  1307. }
  1308. p_arr[RS::ARRAY_VERTEX] = points;
  1309. p_arr[RS::ARRAY_NORMAL] = normals;
  1310. p_arr[RS::ARRAY_TANGENT] = tangents;
  1311. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1312. p_arr[RS::ARRAY_INDEX] = indices;
  1313. }
  1314. void TorusMesh::_bind_methods() {
  1315. ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &TorusMesh::set_inner_radius);
  1316. ClassDB::bind_method(D_METHOD("get_inner_radius"), &TorusMesh::get_inner_radius);
  1317. ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &TorusMesh::set_outer_radius);
  1318. ClassDB::bind_method(D_METHOD("get_outer_radius"), &TorusMesh::get_outer_radius);
  1319. ClassDB::bind_method(D_METHOD("set_rings", "rings"), &TorusMesh::set_rings);
  1320. ClassDB::bind_method(D_METHOD("get_rings"), &TorusMesh::get_rings);
  1321. ClassDB::bind_method(D_METHOD("set_ring_segments", "rings"), &TorusMesh::set_ring_segments);
  1322. ClassDB::bind_method(D_METHOD("get_ring_segments"), &TorusMesh::get_ring_segments);
  1323. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius");
  1324. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius");
  1325. ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "3,128,1"), "set_rings", "get_rings");
  1326. ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_segments", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_segments", "get_ring_segments");
  1327. }
  1328. void TorusMesh::set_inner_radius(const float p_inner_radius) {
  1329. inner_radius = p_inner_radius;
  1330. _request_update();
  1331. }
  1332. float TorusMesh::get_inner_radius() const {
  1333. return inner_radius;
  1334. }
  1335. void TorusMesh::set_outer_radius(const float p_outer_radius) {
  1336. outer_radius = p_outer_radius;
  1337. _request_update();
  1338. }
  1339. float TorusMesh::get_outer_radius() const {
  1340. return outer_radius;
  1341. }
  1342. void TorusMesh::set_rings(const int p_rings) {
  1343. ERR_FAIL_COND(p_rings < 3);
  1344. rings = p_rings;
  1345. _request_update();
  1346. }
  1347. int TorusMesh::get_rings() const {
  1348. return rings;
  1349. }
  1350. void TorusMesh::set_ring_segments(const int p_ring_segments) {
  1351. ERR_FAIL_COND(p_ring_segments < 3);
  1352. ring_segments = p_ring_segments;
  1353. _request_update();
  1354. }
  1355. int TorusMesh::get_ring_segments() const {
  1356. return ring_segments;
  1357. }
  1358. TorusMesh::TorusMesh() {}
  1359. /**
  1360. PointMesh
  1361. */
  1362. void PointMesh::_create_mesh_array(Array &p_arr) const {
  1363. Vector<Vector3> faces;
  1364. faces.resize(1);
  1365. faces.set(0, Vector3(0.0, 0.0, 0.0));
  1366. p_arr[RS::ARRAY_VERTEX] = faces;
  1367. }
  1368. PointMesh::PointMesh() {
  1369. primitive_type = PRIMITIVE_POINTS;
  1370. }
  1371. // TUBE TRAIL
  1372. void TubeTrailMesh::set_radius(const float p_radius) {
  1373. radius = p_radius;
  1374. _request_update();
  1375. }
  1376. float TubeTrailMesh::get_radius() const {
  1377. return radius;
  1378. }
  1379. void TubeTrailMesh::set_radial_steps(const int p_radial_steps) {
  1380. ERR_FAIL_COND(p_radial_steps < 3 || p_radial_steps > 128);
  1381. radial_steps = p_radial_steps;
  1382. _request_update();
  1383. }
  1384. int TubeTrailMesh::get_radial_steps() const {
  1385. return radial_steps;
  1386. }
  1387. void TubeTrailMesh::set_sections(const int p_sections) {
  1388. ERR_FAIL_COND(p_sections < 2 || p_sections > 128);
  1389. sections = p_sections;
  1390. _request_update();
  1391. }
  1392. int TubeTrailMesh::get_sections() const {
  1393. return sections;
  1394. }
  1395. void TubeTrailMesh::set_section_length(float p_section_length) {
  1396. section_length = p_section_length;
  1397. _request_update();
  1398. }
  1399. float TubeTrailMesh::get_section_length() const {
  1400. return section_length;
  1401. }
  1402. void TubeTrailMesh::set_section_rings(const int p_section_rings) {
  1403. ERR_FAIL_COND(p_section_rings < 1 || p_section_rings > 1024);
  1404. section_rings = p_section_rings;
  1405. _request_update();
  1406. }
  1407. int TubeTrailMesh::get_section_rings() const {
  1408. return section_rings;
  1409. }
  1410. void TubeTrailMesh::set_curve(const Ref<Curve> &p_curve) {
  1411. if (curve == p_curve) {
  1412. return;
  1413. }
  1414. if (curve.is_valid()) {
  1415. curve->disconnect("changed", callable_mp(this, &TubeTrailMesh::_curve_changed));
  1416. }
  1417. curve = p_curve;
  1418. if (curve.is_valid()) {
  1419. curve->connect("changed", callable_mp(this, &TubeTrailMesh::_curve_changed));
  1420. }
  1421. _request_update();
  1422. }
  1423. Ref<Curve> TubeTrailMesh::get_curve() const {
  1424. return curve;
  1425. }
  1426. void TubeTrailMesh::_curve_changed() {
  1427. _request_update();
  1428. }
  1429. int TubeTrailMesh::get_builtin_bind_pose_count() const {
  1430. return sections + 1;
  1431. }
  1432. Transform3D TubeTrailMesh::get_builtin_bind_pose(int p_index) const {
  1433. float depth = section_length * sections;
  1434. Transform3D xform;
  1435. xform.origin.y = depth / 2.0 - section_length * float(p_index);
  1436. xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y
  1437. return xform;
  1438. }
  1439. void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
  1440. PackedVector3Array points;
  1441. PackedVector3Array normals;
  1442. PackedFloat32Array tangents;
  1443. PackedVector2Array uvs;
  1444. PackedInt32Array bone_indices;
  1445. PackedFloat32Array bone_weights;
  1446. PackedInt32Array indices;
  1447. int point = 0;
  1448. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1449. tangents.push_back(m_x); \
  1450. tangents.push_back(m_y); \
  1451. tangents.push_back(m_z); \
  1452. tangents.push_back(m_d);
  1453. int thisrow = 0;
  1454. int prevrow = 0;
  1455. int total_rings = section_rings * sections;
  1456. float depth = section_length * sections;
  1457. for (int j = 0; j <= total_rings; j++) {
  1458. float v = j;
  1459. v /= total_rings;
  1460. float y = depth * v;
  1461. y = (depth * 0.5) - y;
  1462. int bone = j / section_rings;
  1463. float blend = 1.0 - float(j % section_rings) / float(section_rings);
  1464. for (int i = 0; i <= radial_steps; i++) {
  1465. float u = i;
  1466. u /= radial_steps;
  1467. float r = radius;
  1468. if (curve.is_valid() && curve->get_point_count() > 0) {
  1469. r *= curve->sample_baked(v);
  1470. }
  1471. float x = sin(u * Math_TAU);
  1472. float z = cos(u * Math_TAU);
  1473. Vector3 p = Vector3(x * r, y, z * r);
  1474. points.push_back(p);
  1475. normals.push_back(Vector3(x, 0, z));
  1476. ADD_TANGENT(z, 0.0, -x, 1.0)
  1477. uvs.push_back(Vector2(u, v * 0.5));
  1478. point++;
  1479. {
  1480. bone_indices.push_back(bone);
  1481. bone_indices.push_back(MIN(sections, bone + 1));
  1482. bone_indices.push_back(0);
  1483. bone_indices.push_back(0);
  1484. bone_weights.push_back(blend);
  1485. bone_weights.push_back(1.0 - blend);
  1486. bone_weights.push_back(0);
  1487. bone_weights.push_back(0);
  1488. }
  1489. if (i > 0 && j > 0) {
  1490. indices.push_back(prevrow + i - 1);
  1491. indices.push_back(prevrow + i);
  1492. indices.push_back(thisrow + i - 1);
  1493. indices.push_back(prevrow + i);
  1494. indices.push_back(thisrow + i);
  1495. indices.push_back(thisrow + i - 1);
  1496. }
  1497. }
  1498. prevrow = thisrow;
  1499. thisrow = point;
  1500. }
  1501. // add top
  1502. float scale_pos = 1.0;
  1503. if (curve.is_valid() && curve->get_point_count() > 0) {
  1504. scale_pos = curve->sample_baked(0);
  1505. }
  1506. if (scale_pos > CMP_EPSILON) {
  1507. float y = depth * 0.5;
  1508. thisrow = point;
  1509. points.push_back(Vector3(0.0, y, 0));
  1510. normals.push_back(Vector3(0.0, 1.0, 0.0));
  1511. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1512. uvs.push_back(Vector2(0.25, 0.75));
  1513. point++;
  1514. bone_indices.push_back(0);
  1515. bone_indices.push_back(0);
  1516. bone_indices.push_back(0);
  1517. bone_indices.push_back(0);
  1518. bone_weights.push_back(1.0);
  1519. bone_weights.push_back(0);
  1520. bone_weights.push_back(0);
  1521. bone_weights.push_back(0);
  1522. float rm = radius * scale_pos;
  1523. for (int i = 0; i <= radial_steps; i++) {
  1524. float r = i;
  1525. r /= radial_steps;
  1526. float x = sin(r * Math_TAU);
  1527. float z = cos(r * Math_TAU);
  1528. float u = ((x + 1.0) * 0.25);
  1529. float v = 0.5 + ((z + 1.0) * 0.25);
  1530. Vector3 p = Vector3(x * rm, y, z * rm);
  1531. points.push_back(p);
  1532. normals.push_back(Vector3(0.0, 1.0, 0.0));
  1533. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1534. uvs.push_back(Vector2(u, v));
  1535. point++;
  1536. bone_indices.push_back(0);
  1537. bone_indices.push_back(0);
  1538. bone_indices.push_back(0);
  1539. bone_indices.push_back(0);
  1540. bone_weights.push_back(1.0);
  1541. bone_weights.push_back(0);
  1542. bone_weights.push_back(0);
  1543. bone_weights.push_back(0);
  1544. if (i > 0) {
  1545. indices.push_back(thisrow);
  1546. indices.push_back(point - 1);
  1547. indices.push_back(point - 2);
  1548. };
  1549. };
  1550. };
  1551. float scale_neg = 1.0;
  1552. if (curve.is_valid() && curve->get_point_count() > 0) {
  1553. scale_neg = curve->sample_baked(1.0);
  1554. }
  1555. // add bottom
  1556. if (scale_neg > CMP_EPSILON) {
  1557. float y = depth * -0.5;
  1558. thisrow = point;
  1559. points.push_back(Vector3(0.0, y, 0.0));
  1560. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1561. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1562. uvs.push_back(Vector2(0.75, 0.75));
  1563. point++;
  1564. bone_indices.push_back(sections);
  1565. bone_indices.push_back(0);
  1566. bone_indices.push_back(0);
  1567. bone_indices.push_back(0);
  1568. bone_weights.push_back(1.0);
  1569. bone_weights.push_back(0);
  1570. bone_weights.push_back(0);
  1571. bone_weights.push_back(0);
  1572. float rm = radius * scale_neg;
  1573. for (int i = 0; i <= radial_steps; i++) {
  1574. float r = i;
  1575. r /= radial_steps;
  1576. float x = sin(r * Math_TAU);
  1577. float z = cos(r * Math_TAU);
  1578. float u = 0.5 + ((x + 1.0) * 0.25);
  1579. float v = 1.0 - ((z + 1.0) * 0.25);
  1580. Vector3 p = Vector3(x * rm, y, z * rm);
  1581. points.push_back(p);
  1582. normals.push_back(Vector3(0.0, -1.0, 0.0));
  1583. ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
  1584. uvs.push_back(Vector2(u, v));
  1585. point++;
  1586. bone_indices.push_back(sections);
  1587. bone_indices.push_back(0);
  1588. bone_indices.push_back(0);
  1589. bone_indices.push_back(0);
  1590. bone_weights.push_back(1.0);
  1591. bone_weights.push_back(0);
  1592. bone_weights.push_back(0);
  1593. bone_weights.push_back(0);
  1594. if (i > 0) {
  1595. indices.push_back(thisrow);
  1596. indices.push_back(point - 2);
  1597. indices.push_back(point - 1);
  1598. };
  1599. };
  1600. };
  1601. p_arr[RS::ARRAY_VERTEX] = points;
  1602. p_arr[RS::ARRAY_NORMAL] = normals;
  1603. p_arr[RS::ARRAY_TANGENT] = tangents;
  1604. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1605. p_arr[RS::ARRAY_BONES] = bone_indices;
  1606. p_arr[RS::ARRAY_WEIGHTS] = bone_weights;
  1607. p_arr[RS::ARRAY_INDEX] = indices;
  1608. }
  1609. void TubeTrailMesh::_bind_methods() {
  1610. ClassDB::bind_method(D_METHOD("set_radius", "radius"), &TubeTrailMesh::set_radius);
  1611. ClassDB::bind_method(D_METHOD("get_radius"), &TubeTrailMesh::get_radius);
  1612. ClassDB::bind_method(D_METHOD("set_radial_steps", "radial_steps"), &TubeTrailMesh::set_radial_steps);
  1613. ClassDB::bind_method(D_METHOD("get_radial_steps"), &TubeTrailMesh::get_radial_steps);
  1614. ClassDB::bind_method(D_METHOD("set_sections", "sections"), &TubeTrailMesh::set_sections);
  1615. ClassDB::bind_method(D_METHOD("get_sections"), &TubeTrailMesh::get_sections);
  1616. ClassDB::bind_method(D_METHOD("set_section_length", "section_length"), &TubeTrailMesh::set_section_length);
  1617. ClassDB::bind_method(D_METHOD("get_section_length"), &TubeTrailMesh::get_section_length);
  1618. ClassDB::bind_method(D_METHOD("set_section_rings", "section_rings"), &TubeTrailMesh::set_section_rings);
  1619. ClassDB::bind_method(D_METHOD("get_section_rings"), &TubeTrailMesh::get_section_rings);
  1620. ClassDB::bind_method(D_METHOD("set_curve", "curve"), &TubeTrailMesh::set_curve);
  1621. ClassDB::bind_method(D_METHOD("get_curve"), &TubeTrailMesh::get_curve);
  1622. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_radius", "get_radius");
  1623. ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_steps", PROPERTY_HINT_RANGE, "3,128,1"), "set_radial_steps", "get_radial_steps");
  1624. ADD_PROPERTY(PropertyInfo(Variant::INT, "sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_sections", "get_sections");
  1625. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "section_length", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001,or_greater,suffix:m"), "set_section_length", "get_section_length");
  1626. ADD_PROPERTY(PropertyInfo(Variant::INT, "section_rings", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_rings", "get_section_rings");
  1627. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
  1628. }
  1629. TubeTrailMesh::TubeTrailMesh() {
  1630. }
  1631. // TUBE TRAIL
  1632. void RibbonTrailMesh::set_shape(Shape p_shape) {
  1633. shape = p_shape;
  1634. _request_update();
  1635. }
  1636. RibbonTrailMesh::Shape RibbonTrailMesh::get_shape() const {
  1637. return shape;
  1638. }
  1639. void RibbonTrailMesh::set_size(const float p_size) {
  1640. size = p_size;
  1641. _request_update();
  1642. }
  1643. float RibbonTrailMesh::get_size() const {
  1644. return size;
  1645. }
  1646. void RibbonTrailMesh::set_sections(const int p_sections) {
  1647. ERR_FAIL_COND(p_sections < 2 || p_sections > 128);
  1648. sections = p_sections;
  1649. _request_update();
  1650. }
  1651. int RibbonTrailMesh::get_sections() const {
  1652. return sections;
  1653. }
  1654. void RibbonTrailMesh::set_section_length(float p_section_length) {
  1655. section_length = p_section_length;
  1656. _request_update();
  1657. }
  1658. float RibbonTrailMesh::get_section_length() const {
  1659. return section_length;
  1660. }
  1661. void RibbonTrailMesh::set_section_segments(const int p_section_segments) {
  1662. ERR_FAIL_COND(p_section_segments < 1 || p_section_segments > 1024);
  1663. section_segments = p_section_segments;
  1664. _request_update();
  1665. }
  1666. int RibbonTrailMesh::get_section_segments() const {
  1667. return section_segments;
  1668. }
  1669. void RibbonTrailMesh::set_curve(const Ref<Curve> &p_curve) {
  1670. if (curve == p_curve) {
  1671. return;
  1672. }
  1673. if (curve.is_valid()) {
  1674. curve->disconnect("changed", callable_mp(this, &RibbonTrailMesh::_curve_changed));
  1675. }
  1676. curve = p_curve;
  1677. if (curve.is_valid()) {
  1678. curve->connect("changed", callable_mp(this, &RibbonTrailMesh::_curve_changed));
  1679. }
  1680. _request_update();
  1681. }
  1682. Ref<Curve> RibbonTrailMesh::get_curve() const {
  1683. return curve;
  1684. }
  1685. void RibbonTrailMesh::_curve_changed() {
  1686. _request_update();
  1687. }
  1688. int RibbonTrailMesh::get_builtin_bind_pose_count() const {
  1689. return sections + 1;
  1690. }
  1691. Transform3D RibbonTrailMesh::get_builtin_bind_pose(int p_index) const {
  1692. float depth = section_length * sections;
  1693. Transform3D xform;
  1694. xform.origin.y = depth / 2.0 - section_length * float(p_index);
  1695. xform.origin.y = -xform.origin.y; //bind is an inverse transform, so negate y
  1696. return xform;
  1697. }
  1698. void RibbonTrailMesh::_create_mesh_array(Array &p_arr) const {
  1699. PackedVector3Array points;
  1700. PackedVector3Array normals;
  1701. PackedFloat32Array tangents;
  1702. PackedVector2Array uvs;
  1703. PackedInt32Array bone_indices;
  1704. PackedFloat32Array bone_weights;
  1705. PackedInt32Array indices;
  1706. #define ADD_TANGENT(m_x, m_y, m_z, m_d) \
  1707. tangents.push_back(m_x); \
  1708. tangents.push_back(m_y); \
  1709. tangents.push_back(m_z); \
  1710. tangents.push_back(m_d);
  1711. int total_segments = section_segments * sections;
  1712. float depth = section_length * sections;
  1713. for (int j = 0; j <= total_segments; j++) {
  1714. float v = j;
  1715. v /= total_segments;
  1716. float y = depth * v;
  1717. y = (depth * 0.5) - y;
  1718. int bone = j / section_segments;
  1719. float blend = 1.0 - float(j % section_segments) / float(section_segments);
  1720. float s = size;
  1721. if (curve.is_valid() && curve->get_point_count() > 0) {
  1722. s *= curve->sample_baked(v);
  1723. }
  1724. points.push_back(Vector3(-s * 0.5, y, 0));
  1725. points.push_back(Vector3(+s * 0.5, y, 0));
  1726. if (shape == SHAPE_CROSS) {
  1727. points.push_back(Vector3(0, y, -s * 0.5));
  1728. points.push_back(Vector3(0, y, +s * 0.5));
  1729. }
  1730. normals.push_back(Vector3(0, 0, 1));
  1731. normals.push_back(Vector3(0, 0, 1));
  1732. if (shape == SHAPE_CROSS) {
  1733. normals.push_back(Vector3(1, 0, 0));
  1734. normals.push_back(Vector3(1, 0, 0));
  1735. }
  1736. uvs.push_back(Vector2(0, v));
  1737. uvs.push_back(Vector2(1, v));
  1738. if (shape == SHAPE_CROSS) {
  1739. uvs.push_back(Vector2(0, v));
  1740. uvs.push_back(Vector2(1, v));
  1741. }
  1742. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  1743. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  1744. if (shape == SHAPE_CROSS) {
  1745. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  1746. ADD_TANGENT(0.0, 1.0, 0.0, 1.0)
  1747. }
  1748. for (int i = 0; i < (shape == SHAPE_CROSS ? 4 : 2); i++) {
  1749. bone_indices.push_back(bone);
  1750. bone_indices.push_back(MIN(sections, bone + 1));
  1751. bone_indices.push_back(0);
  1752. bone_indices.push_back(0);
  1753. bone_weights.push_back(blend);
  1754. bone_weights.push_back(1.0 - blend);
  1755. bone_weights.push_back(0);
  1756. bone_weights.push_back(0);
  1757. }
  1758. if (j > 0) {
  1759. if (shape == SHAPE_CROSS) {
  1760. int base = j * 4 - 4;
  1761. indices.push_back(base + 0);
  1762. indices.push_back(base + 1);
  1763. indices.push_back(base + 4);
  1764. indices.push_back(base + 1);
  1765. indices.push_back(base + 5);
  1766. indices.push_back(base + 4);
  1767. indices.push_back(base + 2);
  1768. indices.push_back(base + 3);
  1769. indices.push_back(base + 6);
  1770. indices.push_back(base + 3);
  1771. indices.push_back(base + 7);
  1772. indices.push_back(base + 6);
  1773. } else {
  1774. int base = j * 2 - 2;
  1775. indices.push_back(base + 0);
  1776. indices.push_back(base + 1);
  1777. indices.push_back(base + 2);
  1778. indices.push_back(base + 1);
  1779. indices.push_back(base + 3);
  1780. indices.push_back(base + 2);
  1781. }
  1782. }
  1783. }
  1784. p_arr[RS::ARRAY_VERTEX] = points;
  1785. p_arr[RS::ARRAY_NORMAL] = normals;
  1786. p_arr[RS::ARRAY_TANGENT] = tangents;
  1787. p_arr[RS::ARRAY_TEX_UV] = uvs;
  1788. p_arr[RS::ARRAY_BONES] = bone_indices;
  1789. p_arr[RS::ARRAY_WEIGHTS] = bone_weights;
  1790. p_arr[RS::ARRAY_INDEX] = indices;
  1791. }
  1792. void RibbonTrailMesh::_bind_methods() {
  1793. ClassDB::bind_method(D_METHOD("set_size", "size"), &RibbonTrailMesh::set_size);
  1794. ClassDB::bind_method(D_METHOD("get_size"), &RibbonTrailMesh::get_size);
  1795. ClassDB::bind_method(D_METHOD("set_sections", "sections"), &RibbonTrailMesh::set_sections);
  1796. ClassDB::bind_method(D_METHOD("get_sections"), &RibbonTrailMesh::get_sections);
  1797. ClassDB::bind_method(D_METHOD("set_section_length", "section_length"), &RibbonTrailMesh::set_section_length);
  1798. ClassDB::bind_method(D_METHOD("get_section_length"), &RibbonTrailMesh::get_section_length);
  1799. ClassDB::bind_method(D_METHOD("set_section_segments", "section_segments"), &RibbonTrailMesh::set_section_segments);
  1800. ClassDB::bind_method(D_METHOD("get_section_segments"), &RibbonTrailMesh::get_section_segments);
  1801. ClassDB::bind_method(D_METHOD("set_curve", "curve"), &RibbonTrailMesh::set_curve);
  1802. ClassDB::bind_method(D_METHOD("get_curve"), &RibbonTrailMesh::get_curve);
  1803. ClassDB::bind_method(D_METHOD("set_shape", "shape"), &RibbonTrailMesh::set_shape);
  1804. ClassDB::bind_method(D_METHOD("get_shape"), &RibbonTrailMesh::get_shape);
  1805. ADD_PROPERTY(PropertyInfo(Variant::INT, "shape", PROPERTY_HINT_ENUM, "Flat,Cross"), "set_shape", "get_shape");
  1806. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater,suffix:m"), "set_size", "get_size");
  1807. ADD_PROPERTY(PropertyInfo(Variant::INT, "sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_sections", "get_sections");
  1808. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "section_length", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001,or_greater,suffix:m"), "set_section_length", "get_section_length");
  1809. ADD_PROPERTY(PropertyInfo(Variant::INT, "section_segments", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_segments", "get_section_segments");
  1810. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
  1811. BIND_ENUM_CONSTANT(SHAPE_FLAT)
  1812. BIND_ENUM_CONSTANT(SHAPE_CROSS)
  1813. }
  1814. RibbonTrailMesh::RibbonTrailMesh() {
  1815. }
  1816. /*************************************************************************/
  1817. /* TextMesh */
  1818. /*************************************************************************/
  1819. void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_gl) const {
  1820. if (cache.has(p_key)) {
  1821. return;
  1822. }
  1823. GlyphMeshData &gl_data = cache[p_key];
  1824. Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index);
  1825. Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size;
  1826. PackedVector3Array points = d["points"];
  1827. PackedInt32Array contours = d["contours"];
  1828. bool orientation = d["orientation"];
  1829. if (points.size() < 3 || contours.size() < 1) {
  1830. return; // No full contours, only glyph control points (or nothing), ignore.
  1831. }
  1832. // Approximate Bezier curves as polygons.
  1833. // See https://freetype.org/freetype2/docs/glyphs/glyphs-6.html, for more info.
  1834. for (int i = 0; i < contours.size(); i++) {
  1835. int32_t start = (i == 0) ? 0 : (contours[i - 1] + 1);
  1836. int32_t end = contours[i];
  1837. Vector<ContourPoint> polygon;
  1838. for (int32_t j = start; j <= end; j++) {
  1839. if (points[j].z == TextServer::CONTOUR_CURVE_TAG_ON) {
  1840. // Point on the curve.
  1841. Vector2 p = Vector2(points[j].x, points[j].y) * pixel_size + origin;
  1842. polygon.push_back(ContourPoint(p, true));
  1843. } else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
  1844. // Conic Bezier arc.
  1845. int32_t next = (j == end) ? start : (j + 1);
  1846. int32_t prev = (j == start) ? end : (j - 1);
  1847. Vector2 p0;
  1848. Vector2 p1 = Vector2(points[j].x, points[j].y);
  1849. Vector2 p2;
  1850. // For successive conic OFF points add a virtual ON point in the middle.
  1851. if (points[prev].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
  1852. p0 = (Vector2(points[prev].x, points[prev].y) + Vector2(points[j].x, points[j].y)) / 2.0;
  1853. } else if (points[prev].z == TextServer::CONTOUR_CURVE_TAG_ON) {
  1854. p0 = Vector2(points[prev].x, points[prev].y);
  1855. } else {
  1856. ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j));
  1857. }
  1858. if (points[next].z == TextServer::CONTOUR_CURVE_TAG_OFF_CONIC) {
  1859. p2 = (Vector2(points[j].x, points[j].y) + Vector2(points[next].x, points[next].y)) / 2.0;
  1860. } else if (points[next].z == TextServer::CONTOUR_CURVE_TAG_ON) {
  1861. p2 = Vector2(points[next].x, points[next].y);
  1862. } else {
  1863. ERR_FAIL_MSG(vformat("Invalid conic arc point sequence at %d:%d", i, j));
  1864. }
  1865. real_t step = CLAMP(curve_step / (p0 - p2).length(), 0.01, 0.5);
  1866. real_t t = step;
  1867. while (t < 1.0) {
  1868. real_t omt = (1.0 - t);
  1869. real_t omt2 = omt * omt;
  1870. real_t t2 = t * t;
  1871. Vector2 point = p1 + omt2 * (p0 - p1) + t2 * (p2 - p1);
  1872. Vector2 p = point * pixel_size + origin;
  1873. polygon.push_back(ContourPoint(p, false));
  1874. t += step;
  1875. }
  1876. } else if (points[j].z == TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC) {
  1877. // Cubic Bezier arc.
  1878. int32_t cur = j;
  1879. int32_t next1 = (j == end) ? start : (j + 1);
  1880. int32_t next2 = (next1 == end) ? start : (next1 + 1);
  1881. int32_t prev = (j == start) ? end : (j - 1);
  1882. // There must be exactly two OFF points and two ON points for each cubic arc.
  1883. if (points[prev].z != TextServer::CONTOUR_CURVE_TAG_ON) {
  1884. cur = (cur == 0) ? end : cur - 1;
  1885. next1 = (next1 == 0) ? end : next1 - 1;
  1886. next2 = (next2 == 0) ? end : next2 - 1;
  1887. prev = (prev == 0) ? end : prev - 1;
  1888. } else {
  1889. j++;
  1890. }
  1891. ERR_FAIL_COND_MSG(points[prev].z != TextServer::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, prev));
  1892. ERR_FAIL_COND_MSG(points[cur].z != TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, cur));
  1893. ERR_FAIL_COND_MSG(points[next1].z != TextServer::CONTOUR_CURVE_TAG_OFF_CUBIC, vformat("Invalid cubic arc point sequence at %d:%d", i, next1));
  1894. ERR_FAIL_COND_MSG(points[next2].z != TextServer::CONTOUR_CURVE_TAG_ON, vformat("Invalid cubic arc point sequence at %d:%d", i, next2));
  1895. Vector2 p0 = Vector2(points[prev].x, points[prev].y);
  1896. Vector2 p1 = Vector2(points[cur].x, points[cur].y);
  1897. Vector2 p2 = Vector2(points[next1].x, points[next1].y);
  1898. Vector2 p3 = Vector2(points[next2].x, points[next2].y);
  1899. real_t step = CLAMP(curve_step / (p0 - p3).length(), 0.01, 0.5);
  1900. real_t t = step;
  1901. while (t < 1.0) {
  1902. real_t omt = (1.0 - t);
  1903. real_t omt2 = omt * omt;
  1904. real_t omt3 = omt2 * omt;
  1905. real_t t2 = t * t;
  1906. real_t t3 = t2 * t;
  1907. Vector2 point = p0 * omt3 + p1 * omt2 * t * 3.0 + p2 * omt * t2 * 3.0 + p3 * t3;
  1908. Vector2 p = point * pixel_size + origin;
  1909. polygon.push_back(ContourPoint(p, false));
  1910. t += step;
  1911. }
  1912. } else {
  1913. ERR_FAIL_MSG(vformat("Unknown point tag at %d:%d", i, j));
  1914. }
  1915. }
  1916. if (polygon.size() < 3) {
  1917. continue; // Skip glyph control points.
  1918. }
  1919. if (!orientation) {
  1920. polygon.reverse();
  1921. }
  1922. gl_data.contours.push_back(polygon);
  1923. }
  1924. // Calculate bounds.
  1925. List<TPPLPoly> in_poly;
  1926. for (int i = 0; i < gl_data.contours.size(); i++) {
  1927. TPPLPoly inp;
  1928. inp.Init(gl_data.contours[i].size());
  1929. real_t length = 0.0;
  1930. for (int j = 0; j < gl_data.contours[i].size(); j++) {
  1931. int next = (j + 1 == gl_data.contours[i].size()) ? 0 : (j + 1);
  1932. gl_data.min_p.x = MIN(gl_data.min_p.x, gl_data.contours[i][j].point.x);
  1933. gl_data.min_p.y = MIN(gl_data.min_p.y, gl_data.contours[i][j].point.y);
  1934. gl_data.max_p.x = MAX(gl_data.max_p.x, gl_data.contours[i][j].point.x);
  1935. gl_data.max_p.y = MAX(gl_data.max_p.y, gl_data.contours[i][j].point.y);
  1936. length += (gl_data.contours[i][next].point - gl_data.contours[i][j].point).length();
  1937. inp.GetPoint(j) = gl_data.contours[i][j].point;
  1938. }
  1939. TPPLOrientation poly_orient = inp.GetOrientation();
  1940. if (poly_orient == TPPL_ORIENTATION_CW) {
  1941. inp.SetHole(true);
  1942. }
  1943. in_poly.push_back(inp);
  1944. gl_data.contours_info.push_back(ContourInfo(length, poly_orient == TPPL_ORIENTATION_CCW));
  1945. }
  1946. TPPLPartition tpart;
  1947. //Decompose and triangulate.
  1948. List<TPPLPoly> out_poly;
  1949. if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) {
  1950. ERR_FAIL_MSG("Convex decomposing failed. Make sure the font doesn't contain self-intersecting lines, as these are not supported in TextMesh.");
  1951. }
  1952. List<TPPLPoly> out_tris;
  1953. for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
  1954. if (tpart.Triangulate_OPT(&(I->get()), &out_tris) == 0) {
  1955. ERR_FAIL_MSG("Triangulation failed. Make sure the font doesn't contain self-intersecting lines, as these are not supported in TextMesh.");
  1956. }
  1957. }
  1958. for (List<TPPLPoly>::Element *I = out_tris.front(); I; I = I->next()) {
  1959. TPPLPoly &tp = I->get();
  1960. ERR_FAIL_COND(tp.GetNumPoints() != 3); // Triangles only.
  1961. for (int i = 0; i < 3; i++) {
  1962. gl_data.triangles.push_back(Vector2(tp.GetPoint(i).x, tp.GetPoint(i).y));
  1963. }
  1964. }
  1965. }
  1966. void TextMesh::_create_mesh_array(Array &p_arr) const {
  1967. Ref<Font> font = _get_font_or_default();
  1968. ERR_FAIL_COND(font.is_null());
  1969. if (dirty_cache) {
  1970. cache.clear();
  1971. dirty_cache = false;
  1972. }
  1973. // Update text buffer.
  1974. if (dirty_text) {
  1975. TS->shaped_text_clear(text_rid);
  1976. TS->shaped_text_set_direction(text_rid, text_direction);
  1977. String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
  1978. TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, font->get_opentype_features(), language);
  1979. for (int i = 0; i < TextServer::SPACING_MAX; i++) {
  1980. TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
  1981. }
  1982. Array stt;
  1983. if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
  1984. GDVIRTUAL_CALL(_structured_text_parser, st_args, text, stt);
  1985. } else {
  1986. stt = TS->parse_structured_text(st_parser, st_args, text);
  1987. }
  1988. TS->shaped_text_set_bidi_override(text_rid, stt);
  1989. dirty_text = false;
  1990. dirty_font = false;
  1991. dirty_lines = true;
  1992. } else if (dirty_font) {
  1993. int spans = TS->shaped_get_span_count(text_rid);
  1994. for (int i = 0; i < spans; i++) {
  1995. TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, font->get_opentype_features());
  1996. }
  1997. for (int i = 0; i < TextServer::SPACING_MAX; i++) {
  1998. TS->shaped_text_set_spacing(text_rid, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i)));
  1999. }
  2000. dirty_font = false;
  2001. dirty_lines = true;
  2002. }
  2003. if (dirty_lines) {
  2004. for (int i = 0; i < lines_rid.size(); i++) {
  2005. TS->free_rid(lines_rid[i]);
  2006. }
  2007. lines_rid.clear();
  2008. BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY;
  2009. switch (autowrap_mode) {
  2010. case TextServer::AUTOWRAP_WORD_SMART:
  2011. autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY;
  2012. break;
  2013. case TextServer::AUTOWRAP_WORD:
  2014. autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
  2015. break;
  2016. case TextServer::AUTOWRAP_ARBITRARY:
  2017. autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
  2018. break;
  2019. case TextServer::AUTOWRAP_OFF:
  2020. break;
  2021. }
  2022. PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
  2023. float max_line_w = 0.0;
  2024. for (int i = 0; i < line_breaks.size(); i = i + 2) {
  2025. RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
  2026. max_line_w = MAX(max_line_w, TS->shaped_text_get_width(line));
  2027. lines_rid.push_back(line);
  2028. }
  2029. if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
  2030. for (int i = 0; i < lines_rid.size() - 1; i++) {
  2031. TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
  2032. }
  2033. }
  2034. dirty_lines = false;
  2035. }
  2036. float total_h = 0.0;
  2037. for (int i = 0; i < lines_rid.size(); i++) {
  2038. total_h += (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size;
  2039. }
  2040. float vbegin = 0.0;
  2041. switch (vertical_alignment) {
  2042. case VERTICAL_ALIGNMENT_FILL:
  2043. case VERTICAL_ALIGNMENT_TOP: {
  2044. // Nothing.
  2045. } break;
  2046. case VERTICAL_ALIGNMENT_CENTER: {
  2047. vbegin = (total_h - line_spacing * pixel_size) / 2.0;
  2048. } break;
  2049. case VERTICAL_ALIGNMENT_BOTTOM: {
  2050. vbegin = (total_h - line_spacing * pixel_size);
  2051. } break;
  2052. }
  2053. Vector<Vector3> vertices;
  2054. Vector<Vector3> normals;
  2055. Vector<float> tangents;
  2056. Vector<Vector2> uvs;
  2057. Vector<int32_t> indices;
  2058. Vector2 min_p = Vector2(INFINITY, INFINITY);
  2059. Vector2 max_p = Vector2(-INFINITY, -INFINITY);
  2060. int32_t p_size = 0;
  2061. int32_t i_size = 0;
  2062. Vector2 offset = Vector2(0, vbegin + lbl_offset.y * pixel_size);
  2063. for (int i = 0; i < lines_rid.size(); i++) {
  2064. const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
  2065. int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]);
  2066. float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size;
  2067. switch (horizontal_alignment) {
  2068. case HORIZONTAL_ALIGNMENT_LEFT:
  2069. offset.x = 0.0;
  2070. break;
  2071. case HORIZONTAL_ALIGNMENT_FILL:
  2072. case HORIZONTAL_ALIGNMENT_CENTER: {
  2073. offset.x = -line_width / 2.0;
  2074. } break;
  2075. case HORIZONTAL_ALIGNMENT_RIGHT: {
  2076. offset.x = -line_width;
  2077. } break;
  2078. }
  2079. offset.x += lbl_offset.x * pixel_size;
  2080. offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
  2081. bool has_depth = !Math::is_zero_approx(depth);
  2082. for (int j = 0; j < gl_size; j++) {
  2083. if (glyphs[j].index == 0) {
  2084. offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat;
  2085. continue;
  2086. }
  2087. if (glyphs[j].font_rid != RID()) {
  2088. GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index);
  2089. _generate_glyph_mesh_data(key, glyphs[j]);
  2090. GlyphMeshData &gl_data = cache[key];
  2091. p_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
  2092. i_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
  2093. if (has_depth) {
  2094. for (int k = 0; k < gl_data.contours.size(); k++) {
  2095. p_size += glyphs[j].repeat * gl_data.contours[k].size() * 4;
  2096. i_size += glyphs[j].repeat * gl_data.contours[k].size() * 6;
  2097. }
  2098. }
  2099. for (int r = 0; r < glyphs[j].repeat; r++) {
  2100. min_p.x = MIN(gl_data.min_p.x + offset.x, min_p.x);
  2101. min_p.y = MIN(gl_data.min_p.y - offset.y, min_p.y);
  2102. max_p.x = MAX(gl_data.max_p.x + offset.x, max_p.x);
  2103. max_p.y = MAX(gl_data.max_p.y - offset.y, max_p.y);
  2104. offset.x += glyphs[j].advance * pixel_size;
  2105. }
  2106. } else {
  2107. p_size += glyphs[j].repeat * 4;
  2108. i_size += glyphs[j].repeat * 6;
  2109. offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat;
  2110. }
  2111. }
  2112. offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size;
  2113. }
  2114. vertices.resize(p_size);
  2115. normals.resize(p_size);
  2116. uvs.resize(p_size);
  2117. tangents.resize(p_size * 4);
  2118. indices.resize(i_size);
  2119. Vector3 *vertices_ptr = vertices.ptrw();
  2120. Vector3 *normals_ptr = normals.ptrw();
  2121. float *tangents_ptr = tangents.ptrw();
  2122. Vector2 *uvs_ptr = uvs.ptrw();
  2123. int32_t *indices_ptr = indices.ptrw();
  2124. // Generate mesh.
  2125. int32_t p_idx = 0;
  2126. int32_t i_idx = 0;
  2127. offset = Vector2(0, vbegin + lbl_offset.y * pixel_size);
  2128. for (int i = 0; i < lines_rid.size(); i++) {
  2129. const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
  2130. int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]);
  2131. float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size;
  2132. switch (horizontal_alignment) {
  2133. case HORIZONTAL_ALIGNMENT_LEFT:
  2134. offset.x = 0.0;
  2135. break;
  2136. case HORIZONTAL_ALIGNMENT_FILL:
  2137. case HORIZONTAL_ALIGNMENT_CENTER: {
  2138. offset.x = -line_width / 2.0;
  2139. } break;
  2140. case HORIZONTAL_ALIGNMENT_RIGHT: {
  2141. offset.x = -line_width;
  2142. } break;
  2143. }
  2144. offset.x += lbl_offset.x * pixel_size;
  2145. offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size;
  2146. bool has_depth = !Math::is_zero_approx(depth);
  2147. // Generate glyph data, precalculate size of the arrays and mesh bounds for UV.
  2148. for (int j = 0; j < gl_size; j++) {
  2149. if (glyphs[j].index == 0) {
  2150. offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat;
  2151. continue;
  2152. }
  2153. if (glyphs[j].font_rid != RID()) {
  2154. GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index);
  2155. _generate_glyph_mesh_data(key, glyphs[j]);
  2156. const GlyphMeshData &gl_data = cache[key];
  2157. int64_t ts = gl_data.triangles.size();
  2158. const Vector2 *ts_ptr = gl_data.triangles.ptr();
  2159. for (int r = 0; r < glyphs[j].repeat; r++) {
  2160. for (int k = 0; k < ts; k += 3) {
  2161. // Add front face.
  2162. for (int l = 0; l < 3; l++) {
  2163. Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0);
  2164. vertices_ptr[p_idx] = point;
  2165. normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0);
  2166. if (has_depth) {
  2167. 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, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0)));
  2168. } else {
  2169. 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, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0)));
  2170. }
  2171. tangents_ptr[p_idx * 4 + 0] = 1.0;
  2172. tangents_ptr[p_idx * 4 + 1] = 0.0;
  2173. tangents_ptr[p_idx * 4 + 2] = 0.0;
  2174. tangents_ptr[p_idx * 4 + 3] = 1.0;
  2175. indices_ptr[i_idx++] = p_idx;
  2176. p_idx++;
  2177. }
  2178. if (has_depth) {
  2179. // Add back face.
  2180. for (int l = 2; l >= 0; l--) {
  2181. Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0);
  2182. vertices_ptr[p_idx] = point;
  2183. normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0);
  2184. 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, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4)));
  2185. tangents_ptr[p_idx * 4 + 0] = -1.0;
  2186. tangents_ptr[p_idx * 4 + 1] = 0.0;
  2187. tangents_ptr[p_idx * 4 + 2] = 0.0;
  2188. tangents_ptr[p_idx * 4 + 3] = 1.0;
  2189. indices_ptr[i_idx++] = p_idx;
  2190. p_idx++;
  2191. }
  2192. }
  2193. }
  2194. // Add sides.
  2195. if (has_depth) {
  2196. for (int k = 0; k < gl_data.contours.size(); k++) {
  2197. int64_t ps = gl_data.contours[k].size();
  2198. const ContourPoint *ps_ptr = gl_data.contours[k].ptr();
  2199. const ContourInfo &ps_info = gl_data.contours_info[k];
  2200. real_t length = 0.0;
  2201. for (int l = 0; l < ps; l++) {
  2202. int prev = (l == 0) ? (ps - 1) : (l - 1);
  2203. int next = (l + 1 == ps) ? 0 : (l + 1);
  2204. Vector2 d1;
  2205. Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized();
  2206. if (ps_ptr[l].sharp) {
  2207. d1 = d2;
  2208. } else {
  2209. d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized();
  2210. }
  2211. real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length();
  2212. Vector3 quad_faces[4] = {
  2213. Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0),
  2214. Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0),
  2215. Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0),
  2216. Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0),
  2217. };
  2218. for (int m = 0; m < 4; m++) {
  2219. const Vector2 &d = ((m % 2) == 0) ? d1 : d2;
  2220. real_t u_pos = ((m % 2) == 0) ? length : length + seg_len;
  2221. vertices_ptr[p_idx + m] = quad_faces[m];
  2222. normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0);
  2223. if (m < 2) {
  2224. 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);
  2225. } else {
  2226. 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);
  2227. }
  2228. tangents_ptr[(p_idx + m) * 4 + 0] = d.x;
  2229. tangents_ptr[(p_idx + m) * 4 + 1] = -d.y;
  2230. tangents_ptr[(p_idx + m) * 4 + 2] = 0.0;
  2231. tangents_ptr[(p_idx + m) * 4 + 3] = 1.0;
  2232. }
  2233. indices_ptr[i_idx++] = p_idx;
  2234. indices_ptr[i_idx++] = p_idx + 1;
  2235. indices_ptr[i_idx++] = p_idx + 2;
  2236. indices_ptr[i_idx++] = p_idx + 1;
  2237. indices_ptr[i_idx++] = p_idx + 3;
  2238. indices_ptr[i_idx++] = p_idx + 2;
  2239. length += seg_len;
  2240. p_idx += 4;
  2241. }
  2242. }
  2243. }
  2244. offset.x += glyphs[j].advance * pixel_size;
  2245. }
  2246. } else {
  2247. // Add fallback quad for missing glyphs.
  2248. for (int r = 0; r < glyphs[j].repeat; r++) {
  2249. Size2 sz = TS->get_hex_code_box_size(glyphs[j].font_size, glyphs[j].index) * pixel_size;
  2250. Vector3 quad_faces[4] = {
  2251. Vector3(offset.x, offset.y, 0.0),
  2252. Vector3(offset.x, sz.y + offset.y, 0.0),
  2253. Vector3(sz.x + offset.x, sz.y + offset.y, 0.0),
  2254. Vector3(sz.x + offset.x, offset.y, 0.0),
  2255. };
  2256. for (int k = 0; k < 4; k++) {
  2257. vertices_ptr[p_idx + k] = quad_faces[k];
  2258. normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0);
  2259. if (has_depth) {
  2260. uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0)));
  2261. } else {
  2262. uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0)));
  2263. }
  2264. tangents_ptr[(p_idx + k) * 4 + 0] = 1.0;
  2265. tangents_ptr[(p_idx + k) * 4 + 1] = 0.0;
  2266. tangents_ptr[(p_idx + k) * 4 + 2] = 0.0;
  2267. tangents_ptr[(p_idx + k) * 4 + 3] = 1.0;
  2268. }
  2269. indices_ptr[i_idx++] = p_idx;
  2270. indices_ptr[i_idx++] = p_idx + 1;
  2271. indices_ptr[i_idx++] = p_idx + 2;
  2272. indices_ptr[i_idx++] = p_idx + 0;
  2273. indices_ptr[i_idx++] = p_idx + 2;
  2274. indices_ptr[i_idx++] = p_idx + 3;
  2275. p_idx += 4;
  2276. offset.x += glyphs[j].advance * pixel_size;
  2277. }
  2278. }
  2279. }
  2280. offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size;
  2281. }
  2282. if (indices.is_empty()) {
  2283. // If empty, add single triangle to suppress errors.
  2284. vertices.push_back(Vector3());
  2285. normals.push_back(Vector3());
  2286. uvs.push_back(Vector2());
  2287. tangents.push_back(1.0);
  2288. tangents.push_back(0.0);
  2289. tangents.push_back(0.0);
  2290. tangents.push_back(1.0);
  2291. indices.push_back(0);
  2292. indices.push_back(0);
  2293. indices.push_back(0);
  2294. }
  2295. p_arr[RS::ARRAY_VERTEX] = vertices;
  2296. p_arr[RS::ARRAY_NORMAL] = normals;
  2297. p_arr[RS::ARRAY_TANGENT] = tangents;
  2298. p_arr[RS::ARRAY_TEX_UV] = uvs;
  2299. p_arr[RS::ARRAY_INDEX] = indices;
  2300. }
  2301. void TextMesh::_bind_methods() {
  2302. ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &TextMesh::set_horizontal_alignment);
  2303. ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &TextMesh::get_horizontal_alignment);
  2304. ClassDB::bind_method(D_METHOD("set_vertical_alignment", "alignment"), &TextMesh::set_vertical_alignment);
  2305. ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &TextMesh::get_vertical_alignment);
  2306. ClassDB::bind_method(D_METHOD("set_text", "text"), &TextMesh::set_text);
  2307. ClassDB::bind_method(D_METHOD("get_text"), &TextMesh::get_text);
  2308. ClassDB::bind_method(D_METHOD("set_font", "font"), &TextMesh::set_font);
  2309. ClassDB::bind_method(D_METHOD("get_font"), &TextMesh::get_font);
  2310. ClassDB::bind_method(D_METHOD("set_font_size", "font_size"), &TextMesh::set_font_size);
  2311. ClassDB::bind_method(D_METHOD("get_font_size"), &TextMesh::get_font_size);
  2312. ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextMesh::set_line_spacing);
  2313. ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextMesh::get_line_spacing);
  2314. ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &TextMesh::set_autowrap_mode);
  2315. ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &TextMesh::get_autowrap_mode);
  2316. ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth);
  2317. ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth);
  2318. ClassDB::bind_method(D_METHOD("set_width", "width"), &TextMesh::set_width);
  2319. ClassDB::bind_method(D_METHOD("get_width"), &TextMesh::get_width);
  2320. ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &TextMesh::set_pixel_size);
  2321. ClassDB::bind_method(D_METHOD("get_pixel_size"), &TextMesh::get_pixel_size);
  2322. ClassDB::bind_method(D_METHOD("set_offset", "offset"), &TextMesh::set_offset);
  2323. ClassDB::bind_method(D_METHOD("get_offset"), &TextMesh::get_offset);
  2324. ClassDB::bind_method(D_METHOD("set_curve_step", "curve_step"), &TextMesh::set_curve_step);
  2325. ClassDB::bind_method(D_METHOD("get_curve_step"), &TextMesh::get_curve_step);
  2326. ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &TextMesh::set_text_direction);
  2327. ClassDB::bind_method(D_METHOD("get_text_direction"), &TextMesh::get_text_direction);
  2328. ClassDB::bind_method(D_METHOD("set_language", "language"), &TextMesh::set_language);
  2329. ClassDB::bind_method(D_METHOD("get_language"), &TextMesh::get_language);
  2330. ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &TextMesh::set_structured_text_bidi_override);
  2331. ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &TextMesh::get_structured_text_bidi_override);
  2332. ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override_options", "args"), &TextMesh::set_structured_text_bidi_override_options);
  2333. ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &TextMesh::get_structured_text_bidi_override_options);
  2334. ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &TextMesh::set_uppercase);
  2335. ClassDB::bind_method(D_METHOD("is_uppercase"), &TextMesh::is_uppercase);
  2336. ClassDB::bind_method(D_METHOD("_font_changed"), &TextMesh::_font_changed);
  2337. ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update);
  2338. ADD_GROUP("Text", "");
  2339. ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
  2340. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
  2341. ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size");
  2342. ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
  2343. ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment");
  2344. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
  2345. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing");
  2346. ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
  2347. ADD_GROUP("Mesh", "");
  2348. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size");
  2349. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1,suffix:px"), "set_curve_step", "get_curve_step");
  2350. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth");
  2351. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:m"), "set_width", "get_width");
  2352. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
  2353. ADD_GROUP("BiDi", "");
  2354. ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
  2355. ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
  2356. ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
  2357. ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
  2358. }
  2359. void TextMesh::_notification(int p_what) {
  2360. switch (p_what) {
  2361. case MainLoop::NOTIFICATION_TRANSLATION_CHANGED: {
  2362. String new_text = tr(text);
  2363. if (new_text == xl_text) {
  2364. return; // Nothing new.
  2365. }
  2366. xl_text = new_text;
  2367. dirty_text = true;
  2368. _request_update();
  2369. } break;
  2370. }
  2371. }
  2372. TextMesh::TextMesh() {
  2373. primitive_type = PRIMITIVE_TRIANGLES;
  2374. text_rid = TS->create_shaped_text();
  2375. }
  2376. TextMesh::~TextMesh() {
  2377. for (int i = 0; i < lines_rid.size(); i++) {
  2378. TS->free_rid(lines_rid[i]);
  2379. }
  2380. lines_rid.clear();
  2381. TS->free_rid(text_rid);
  2382. }
  2383. void TextMesh::set_horizontal_alignment(HorizontalAlignment p_alignment) {
  2384. ERR_FAIL_INDEX((int)p_alignment, 4);
  2385. if (horizontal_alignment != p_alignment) {
  2386. if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
  2387. dirty_lines = true;
  2388. }
  2389. horizontal_alignment = p_alignment;
  2390. _request_update();
  2391. }
  2392. }
  2393. HorizontalAlignment TextMesh::get_horizontal_alignment() const {
  2394. return horizontal_alignment;
  2395. }
  2396. void TextMesh::set_vertical_alignment(VerticalAlignment p_alignment) {
  2397. ERR_FAIL_INDEX((int)p_alignment, 4);
  2398. if (vertical_alignment != p_alignment) {
  2399. vertical_alignment = p_alignment;
  2400. _request_update();
  2401. }
  2402. }
  2403. VerticalAlignment TextMesh::get_vertical_alignment() const {
  2404. return vertical_alignment;
  2405. }
  2406. void TextMesh::set_text(const String &p_string) {
  2407. if (text != p_string) {
  2408. text = p_string;
  2409. xl_text = tr(text);
  2410. dirty_text = true;
  2411. _request_update();
  2412. }
  2413. }
  2414. String TextMesh::get_text() const {
  2415. return text;
  2416. }
  2417. void TextMesh::_font_changed() {
  2418. dirty_font = true;
  2419. dirty_cache = true;
  2420. call_deferred(SNAME("_request_update"));
  2421. }
  2422. void TextMesh::set_font(const Ref<Font> &p_font) {
  2423. if (font_override != p_font) {
  2424. if (font_override.is_valid()) {
  2425. font_override->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed"));
  2426. }
  2427. font_override = p_font;
  2428. dirty_font = true;
  2429. dirty_cache = true;
  2430. if (font_override.is_valid()) {
  2431. font_override->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed"));
  2432. }
  2433. _request_update();
  2434. }
  2435. }
  2436. Ref<Font> TextMesh::get_font() const {
  2437. return font_override;
  2438. }
  2439. Ref<Font> TextMesh::_get_font_or_default() const {
  2440. if (font_override.is_valid()) {
  2441. return font_override;
  2442. }
  2443. // Check the project-defined Theme resource.
  2444. if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
  2445. List<StringName> theme_types;
  2446. ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
  2447. for (const StringName &E : theme_types) {
  2448. if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
  2449. return ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
  2450. }
  2451. }
  2452. }
  2453. // Lastly, fall back on the items defined in the default Theme, if they exist.
  2454. {
  2455. List<StringName> theme_types;
  2456. ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
  2457. for (const StringName &E : theme_types) {
  2458. if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
  2459. return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
  2460. }
  2461. }
  2462. }
  2463. // If they don't exist, use any type to return the default/empty value.
  2464. return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
  2465. }
  2466. void TextMesh::set_font_size(int p_size) {
  2467. if (font_size != p_size) {
  2468. font_size = CLAMP(p_size, 1, 127);
  2469. dirty_font = true;
  2470. dirty_cache = true;
  2471. _request_update();
  2472. }
  2473. }
  2474. int TextMesh::get_font_size() const {
  2475. return font_size;
  2476. }
  2477. void TextMesh::set_line_spacing(float p_line_spacing) {
  2478. if (line_spacing != p_line_spacing) {
  2479. line_spacing = p_line_spacing;
  2480. _request_update();
  2481. }
  2482. }
  2483. float TextMesh::get_line_spacing() const {
  2484. return line_spacing;
  2485. }
  2486. void TextMesh::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
  2487. if (autowrap_mode != p_mode) {
  2488. autowrap_mode = p_mode;
  2489. dirty_lines = true;
  2490. _request_update();
  2491. }
  2492. }
  2493. TextServer::AutowrapMode TextMesh::get_autowrap_mode() const {
  2494. return autowrap_mode;
  2495. }
  2496. void TextMesh::set_depth(real_t p_depth) {
  2497. if (depth != p_depth) {
  2498. depth = MAX(p_depth, 0.0);
  2499. _request_update();
  2500. }
  2501. }
  2502. real_t TextMesh::get_depth() const {
  2503. return depth;
  2504. }
  2505. void TextMesh::set_width(real_t p_width) {
  2506. if (width != p_width) {
  2507. width = p_width;
  2508. dirty_lines = true;
  2509. _request_update();
  2510. }
  2511. }
  2512. real_t TextMesh::get_width() const {
  2513. return width;
  2514. }
  2515. void TextMesh::set_pixel_size(real_t p_amount) {
  2516. if (pixel_size != p_amount) {
  2517. pixel_size = CLAMP(p_amount, 0.0001, 128.0);
  2518. dirty_cache = true;
  2519. _request_update();
  2520. }
  2521. }
  2522. real_t TextMesh::get_pixel_size() const {
  2523. return pixel_size;
  2524. }
  2525. void TextMesh::set_offset(const Point2 &p_offset) {
  2526. if (lbl_offset != p_offset) {
  2527. lbl_offset = p_offset;
  2528. _request_update();
  2529. }
  2530. }
  2531. Point2 TextMesh::get_offset() const {
  2532. return lbl_offset;
  2533. }
  2534. void TextMesh::set_curve_step(real_t p_step) {
  2535. if (curve_step != p_step) {
  2536. curve_step = CLAMP(p_step, 0.1, 10.0);
  2537. dirty_cache = true;
  2538. _request_update();
  2539. }
  2540. }
  2541. real_t TextMesh::get_curve_step() const {
  2542. return curve_step;
  2543. }
  2544. void TextMesh::set_text_direction(TextServer::Direction p_text_direction) {
  2545. ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
  2546. if (text_direction != p_text_direction) {
  2547. text_direction = p_text_direction;
  2548. dirty_text = true;
  2549. _request_update();
  2550. }
  2551. }
  2552. TextServer::Direction TextMesh::get_text_direction() const {
  2553. return text_direction;
  2554. }
  2555. void TextMesh::set_language(const String &p_language) {
  2556. if (language != p_language) {
  2557. language = p_language;
  2558. dirty_text = true;
  2559. _request_update();
  2560. }
  2561. }
  2562. String TextMesh::get_language() const {
  2563. return language;
  2564. }
  2565. void TextMesh::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
  2566. if (st_parser != p_parser) {
  2567. st_parser = p_parser;
  2568. dirty_text = true;
  2569. _request_update();
  2570. }
  2571. }
  2572. TextServer::StructuredTextParser TextMesh::get_structured_text_bidi_override() const {
  2573. return st_parser;
  2574. }
  2575. void TextMesh::set_structured_text_bidi_override_options(Array p_args) {
  2576. if (st_args != p_args) {
  2577. st_args = p_args;
  2578. dirty_text = true;
  2579. _request_update();
  2580. }
  2581. }
  2582. Array TextMesh::get_structured_text_bidi_override_options() const {
  2583. return st_args;
  2584. }
  2585. void TextMesh::set_uppercase(bool p_uppercase) {
  2586. if (uppercase != p_uppercase) {
  2587. uppercase = p_uppercase;
  2588. dirty_text = true;
  2589. _request_update();
  2590. }
  2591. }
  2592. bool TextMesh::is_uppercase() const {
  2593. return uppercase;
  2594. }