example.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /* godot-cpp integration testing project.
  2. *
  3. * This is free and unencumbered software released into the public domain.
  4. */
  5. #include "example.h"
  6. #include <godot_cpp/core/class_db.hpp>
  7. #include <godot_cpp/classes/global_constants.hpp>
  8. #include <godot_cpp/classes/label.hpp>
  9. #include <godot_cpp/classes/multiplayer_api.hpp>
  10. #include <godot_cpp/classes/multiplayer_peer.hpp>
  11. #include <godot_cpp/variant/utility_functions.hpp>
  12. using namespace godot;
  13. void ExampleRef::set_id(int p_id) {
  14. id = p_id;
  15. }
  16. int ExampleRef::get_id() const {
  17. return id;
  18. }
  19. void ExampleRef::_bind_methods() {
  20. ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
  21. ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
  22. ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
  23. }
  24. ExampleRef::ExampleRef() {
  25. id = 0;
  26. }
  27. ExampleRef::~ExampleRef() {
  28. }
  29. int Example::test_static(int p_a, int p_b) {
  30. return p_a + p_b;
  31. }
  32. void Example::test_static2() {
  33. //UtilityFunctions::print(" void static");
  34. }
  35. int Example::def_args(int p_a, int p_b) {
  36. return p_a + p_b;
  37. }
  38. void Example::_notification(int p_what) {
  39. if (p_what == NOTIFICATION_READY) {
  40. Dictionary opts;
  41. opts["rpc_mode"] = MultiplayerAPI::RPC_MODE_AUTHORITY;
  42. opts["transfer_mode"] = MultiplayerPeer::TRANSFER_MODE_RELIABLE;
  43. opts["call_local"] = true;
  44. opts["channel"] = 0;
  45. rpc_config("test_rpc", opts);
  46. }
  47. //UtilityFunctions::print("Notification: ", String::num(p_what));
  48. }
  49. bool Example::_set(const StringName &p_name, const Variant &p_value) {
  50. String name = p_name;
  51. if (name.begins_with("dproperty")) {
  52. int64_t index = name.get_slicec('_', 1).to_int();
  53. dprop[index] = p_value;
  54. return true;
  55. }
  56. if (name == "property_from_list") {
  57. property_from_list = p_value;
  58. return true;
  59. }
  60. return false;
  61. }
  62. bool Example::_get(const StringName &p_name, Variant &r_ret) const {
  63. String name = p_name;
  64. if (name.begins_with("dproperty")) {
  65. int64_t index = name.get_slicec('_', 1).to_int();
  66. r_ret = dprop[index];
  67. return true;
  68. }
  69. if (name == "property_from_list") {
  70. r_ret = property_from_list;
  71. return true;
  72. }
  73. return false;
  74. }
  75. String Example::_to_string() const {
  76. return "[ GDExtension::Example <--> Instance ID:" + uitos(get_instance_id()) + " ]";
  77. }
  78. void Example::_get_property_list(List<PropertyInfo> *p_list) const {
  79. p_list->push_back(PropertyInfo(Variant::VECTOR3, "property_from_list"));
  80. for (int i = 0; i < 3; i++) {
  81. p_list->push_back(PropertyInfo(Variant::VECTOR2, "dproperty_" + itos(i)));
  82. }
  83. }
  84. bool Example::_property_can_revert(const StringName &p_name) const {
  85. if (p_name == StringName("property_from_list") && property_from_list != Vector3(42, 42, 42)) {
  86. return true;
  87. } else {
  88. return false;
  89. }
  90. };
  91. bool Example::_property_get_revert(const StringName &p_name, Variant &r_property) const {
  92. if (p_name == StringName("property_from_list")) {
  93. r_property = Vector3(42, 42, 42);
  94. return true;
  95. } else {
  96. return false;
  97. }
  98. };
  99. void Example::_validate_property(PropertyInfo &p_property) const {
  100. String name = p_property.name;
  101. // Test hiding the "mouse_filter" property from the editor.
  102. if (name == "mouse_filter") {
  103. p_property.usage = PROPERTY_USAGE_NO_EDITOR;
  104. }
  105. }
  106. void Example::_bind_methods() {
  107. // Methods.
  108. ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
  109. ClassDB::bind_method(D_METHOD("simple_const_func"), &Example::simple_const_func);
  110. ClassDB::bind_method(D_METHOD("custom_ref_func", "ref"), &Example::custom_ref_func);
  111. ClassDB::bind_method(D_METHOD("custom_const_ref_func", "ref"), &Example::custom_const_ref_func);
  112. ClassDB::bind_method(D_METHOD("image_ref_func", "image"), &Example::image_ref_func);
  113. ClassDB::bind_method(D_METHOD("image_const_ref_func", "image"), &Example::image_const_ref_func);
  114. ClassDB::bind_method(D_METHOD("return_something"), &Example::return_something);
  115. ClassDB::bind_method(D_METHOD("return_something_const"), &Example::return_something_const);
  116. ClassDB::bind_method(D_METHOD("return_empty_ref"), &Example::return_empty_ref);
  117. ClassDB::bind_method(D_METHOD("return_extended_ref"), &Example::return_extended_ref);
  118. ClassDB::bind_method(D_METHOD("extended_ref_checks", "ref"), &Example::extended_ref_checks);
  119. ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array);
  120. ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg);
  121. ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray);
  122. ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
  123. ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
  124. ClassDB::bind_method(D_METHOD("test_string_ops"), &Example::test_string_ops);
  125. ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility);
  126. ClassDB::bind_method(D_METHOD("test_string_is_fourty_two"), &Example::test_string_is_fourty_two);
  127. ClassDB::bind_method(D_METHOD("test_string_resize"), &Example::test_string_resize);
  128. ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops);
  129. ClassDB::bind_method(D_METHOD("test_object_cast_to_node", "object"), &Example::test_object_cast_to_node);
  130. ClassDB::bind_method(D_METHOD("test_object_cast_to_control", "object"), &Example::test_object_cast_to_control);
  131. ClassDB::bind_method(D_METHOD("test_object_cast_to_example", "object"), &Example::test_object_cast_to_example);
  132. ClassDB::bind_method(D_METHOD("test_variant_vector2i_conversion", "variant"), &Example::test_variant_vector2i_conversion);
  133. ClassDB::bind_method(D_METHOD("test_variant_int_conversion", "variant"), &Example::test_variant_int_conversion);
  134. ClassDB::bind_method(D_METHOD("test_variant_float_conversion", "variant"), &Example::test_variant_float_conversion);
  135. ClassDB::bind_method(D_METHOD("test_add_child", "node"), &Example::test_add_child);
  136. ClassDB::bind_method(D_METHOD("test_set_tileset", "tilemap", "tileset"), &Example::test_set_tileset);
  137. ClassDB::bind_method(D_METHOD("test_variant_call", "variant"), &Example::test_variant_call);
  138. ClassDB::bind_method(D_METHOD("test_callable_mp"), &Example::test_callable_mp);
  139. ClassDB::bind_method(D_METHOD("test_callable_mp_ret"), &Example::test_callable_mp_ret);
  140. ClassDB::bind_method(D_METHOD("test_callable_mp_retc"), &Example::test_callable_mp_retc);
  141. ClassDB::bind_method(D_METHOD("test_callable_mp_static"), &Example::test_callable_mp_static);
  142. ClassDB::bind_method(D_METHOD("test_callable_mp_static_ret"), &Example::test_callable_mp_static_ret);
  143. ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
  144. ClassDB::bind_method(D_METHOD("test_variant_iterator", "input"), &Example::test_variant_iterator);
  145. ClassDB::bind_method(D_METHOD("test_rpc", "value"), &Example::test_rpc);
  146. ClassDB::bind_method(D_METHOD("test_send_rpc", "value"), &Example::test_send_rpc);
  147. ClassDB::bind_method(D_METHOD("return_last_rpc_arg"), &Example::return_last_rpc_arg);
  148. ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
  149. ClassDB::bind_method(D_METHOD("callable_bind"), &Example::callable_bind);
  150. ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
  151. ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
  152. {
  153. MethodInfo mi;
  154. mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
  155. mi.name = "varargs_func";
  156. ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func", &Example::varargs_func, mi);
  157. }
  158. {
  159. MethodInfo mi;
  160. mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
  161. mi.name = "varargs_func_nv";
  162. ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func_nv", &Example::varargs_func_nv, mi);
  163. }
  164. {
  165. MethodInfo mi;
  166. mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
  167. mi.name = "varargs_func_void";
  168. ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "varargs_func_void", &Example::varargs_func_void, mi);
  169. }
  170. // Properties.
  171. ADD_GROUP("Test group", "group_");
  172. ADD_SUBGROUP("Test subgroup", "group_subgroup_");
  173. ClassDB::bind_method(D_METHOD("get_custom_position"), &Example::get_custom_position);
  174. ClassDB::bind_method(D_METHOD("get_v4"), &Example::get_v4);
  175. ClassDB::bind_method(D_METHOD("set_custom_position", "position"), &Example::set_custom_position);
  176. ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "group_subgroup_custom_position"), "set_custom_position", "get_custom_position");
  177. // Signals.
  178. ADD_SIGNAL(MethodInfo("custom_signal", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "value")));
  179. ClassDB::bind_method(D_METHOD("emit_custom_signal", "name", "value"), &Example::emit_custom_signal);
  180. // Constants.
  181. BIND_ENUM_CONSTANT(FIRST);
  182. BIND_ENUM_CONSTANT(ANSWER_TO_EVERYTHING);
  183. BIND_BITFIELD_FLAG(FLAG_ONE);
  184. BIND_BITFIELD_FLAG(FLAG_TWO);
  185. BIND_CONSTANT(CONSTANT_WITHOUT_ENUM);
  186. BIND_ENUM_CONSTANT(OUTSIDE_OF_CLASS);
  187. }
  188. Example::Example() {
  189. //UtilityFunctions::print("Constructor.");
  190. }
  191. Example::~Example() {
  192. //UtilityFunctions::print("Destructor.");
  193. }
  194. // Methods.
  195. void Example::simple_func() {
  196. emit_custom_signal("simple_func", 3);
  197. }
  198. void Example::simple_const_func() const {
  199. ((Example *)this)->emit_custom_signal("simple_const_func", 4);
  200. }
  201. int Example::custom_ref_func(Ref<ExampleRef> p_ref) {
  202. return p_ref.is_valid() ? p_ref->get_id() : -1;
  203. }
  204. int Example::custom_const_ref_func(const Ref<ExampleRef> &p_ref) {
  205. return p_ref.is_valid() ? p_ref->get_id() : -1;
  206. }
  207. String Example::image_ref_func(Ref<Image> p_image) {
  208. return p_image.is_valid() ? String("valid") : String("invalid");
  209. }
  210. String Example::image_const_ref_func(const Ref<Image> &p_image) {
  211. return p_image.is_valid() ? String("valid") : String("invalid");
  212. }
  213. String Example::return_something(const String &base) {
  214. return base + String("42");
  215. }
  216. Viewport *Example::return_something_const() const {
  217. if (is_inside_tree()) {
  218. Viewport *result = get_viewport();
  219. return result;
  220. }
  221. return nullptr;
  222. }
  223. Ref<ExampleRef> Example::return_empty_ref() const {
  224. Ref<ExampleRef> ref;
  225. return ref;
  226. }
  227. ExampleRef *Example::return_extended_ref() const {
  228. // You can instance and return a refcounted object like this, but keep in mind that refcounting starts with the returned object
  229. // and it will be destroyed when all references are destroyed. If you store this pointer you run the risk of having a pointer
  230. // to a destroyed object.
  231. return memnew(ExampleRef());
  232. }
  233. Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
  234. // This is therefor the prefered way of instancing and returning a refcounted object:
  235. Ref<ExampleRef> ref;
  236. ref.instantiate();
  237. return ref;
  238. }
  239. Variant Example::varargs_func(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
  240. return arg_count;
  241. }
  242. int Example::varargs_func_nv(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
  243. return 42 + arg_count;
  244. }
  245. void Example::varargs_func_void(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
  246. emit_custom_signal("varargs_func_void", arg_count + 1);
  247. }
  248. void Example::emit_custom_signal(const String &name, int value) {
  249. emit_signal("custom_signal", name, value);
  250. }
  251. Array Example::test_array() const {
  252. Array arr;
  253. arr.resize(2);
  254. arr[0] = Variant(1);
  255. arr[1] = Variant(2);
  256. return arr;
  257. }
  258. String Example::test_string_ops() const {
  259. String s = String("A");
  260. s += "B";
  261. s += "C";
  262. s += char32_t(0x010E);
  263. s = s + "E";
  264. return s;
  265. }
  266. String Example::test_str_utility() const {
  267. return UtilityFunctions::str("Hello, ", "World", "! The answer is ", 42);
  268. }
  269. bool Example::test_string_is_fourty_two(const String &p_string) const {
  270. return strcmp(p_string.utf8().ptr(), "fourty two") == 0;
  271. }
  272. String Example::test_string_resize(String p_string) const {
  273. int orig_len = p_string.length();
  274. p_string.resize(orig_len + 3);
  275. char32_t *data = p_string.ptrw();
  276. data[orig_len + 0] = '!';
  277. data[orig_len + 1] = '?';
  278. data[orig_len + 2] = '\0';
  279. return p_string;
  280. }
  281. int Example::test_vector_ops() const {
  282. PackedInt32Array arr;
  283. arr.push_back(10);
  284. arr.push_back(20);
  285. arr.push_back(30);
  286. arr.push_back(45);
  287. int ret = 0;
  288. for (const int32_t &E : arr) {
  289. ret += E;
  290. }
  291. return ret;
  292. }
  293. Callable Example::test_callable_mp() {
  294. return callable_mp(this, &Example::unbound_method1);
  295. }
  296. Callable Example::test_callable_mp_ret() {
  297. return callable_mp(this, &Example::unbound_method2);
  298. }
  299. Callable Example::test_callable_mp_retc() const {
  300. return callable_mp(this, &Example::unbound_method3);
  301. }
  302. Callable Example::test_callable_mp_static() const {
  303. return callable_mp_static(&Example::unbound_static_method1);
  304. }
  305. Callable Example::test_callable_mp_static_ret() const {
  306. return callable_mp_static(&Example::unbound_static_method2);
  307. }
  308. void Example::unbound_method1(Object *p_object, String p_string, int p_int) {
  309. String test = "unbound_method1: ";
  310. test += p_object->get_class();
  311. test += " - " + p_string;
  312. emit_custom_signal(test, p_int);
  313. }
  314. String Example::unbound_method2(Object *p_object, String p_string, int p_int) {
  315. String test = "unbound_method2: ";
  316. test += p_object->get_class();
  317. test += " - " + p_string;
  318. test += " - " + itos(p_int);
  319. return test;
  320. }
  321. String Example::unbound_method3(Object *p_object, String p_string, int p_int) const {
  322. String test = "unbound_method3: ";
  323. test += p_object->get_class();
  324. test += " - " + p_string;
  325. test += " - " + itos(p_int);
  326. return test;
  327. }
  328. void Example::unbound_static_method1(Example *p_object, String p_string, int p_int) {
  329. String test = "unbound_static_method1: ";
  330. test += p_object->get_class();
  331. test += " - " + p_string;
  332. p_object->emit_custom_signal(test, p_int);
  333. }
  334. String Example::unbound_static_method2(Object *p_object, String p_string, int p_int) {
  335. String test = "unbound_static_method2: ";
  336. test += p_object->get_class();
  337. test += " - " + p_string;
  338. test += " - " + itos(p_int);
  339. return test;
  340. }
  341. int Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
  342. int sum = 0;
  343. for (int i = 0; i < p_array.size(); i++) {
  344. sum += (int)p_array[i];
  345. }
  346. return sum;
  347. }
  348. TypedArray<Vector2> Example::test_tarray() const {
  349. TypedArray<Vector2> arr;
  350. arr.resize(2);
  351. arr[0] = Vector2(1, 2);
  352. arr[1] = Vector2(2, 3);
  353. return arr;
  354. }
  355. Dictionary Example::test_dictionary() const {
  356. Dictionary dict;
  357. dict["hello"] = "world";
  358. dict["foo"] = "bar";
  359. return dict;
  360. }
  361. Example *Example::test_node_argument(Example *p_node) const {
  362. return p_node;
  363. }
  364. bool Example::test_object_cast_to_node(Object *p_object) const {
  365. return Object::cast_to<Node>(p_object) != nullptr;
  366. }
  367. bool Example::test_object_cast_to_control(Object *p_object) const {
  368. return Object::cast_to<Control>(p_object) != nullptr;
  369. }
  370. bool Example::test_object_cast_to_example(Object *p_object) const {
  371. return Object::cast_to<Example>(p_object) != nullptr;
  372. }
  373. Vector2i Example::test_variant_vector2i_conversion(const Variant &p_variant) const {
  374. return p_variant;
  375. }
  376. int Example::test_variant_int_conversion(const Variant &p_variant) const {
  377. return p_variant;
  378. }
  379. float Example::test_variant_float_conversion(const Variant &p_variant) const {
  380. return p_variant;
  381. }
  382. void Example::test_add_child(Node *p_node) {
  383. add_child(p_node);
  384. }
  385. void Example::test_set_tileset(TileMap *p_tilemap, const Ref<TileSet> &p_tileset) const {
  386. p_tilemap->set_tileset(p_tileset);
  387. }
  388. Variant Example::test_variant_call(Variant p_variant) {
  389. return p_variant.call("test", "hello");
  390. }
  391. BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
  392. return flags;
  393. }
  394. Variant Example::test_variant_iterator(const Variant &p_input) {
  395. Array output;
  396. Variant iter;
  397. bool is_init_valid = true;
  398. if (!p_input.iter_init(iter, is_init_valid)) {
  399. if (!is_init_valid) {
  400. return "iter_init: not valid";
  401. }
  402. return output;
  403. }
  404. bool is_iter_next_valid = true;
  405. bool is_iter_get_valid = true;
  406. do {
  407. if (!is_iter_next_valid) {
  408. return "iter_next: not valid";
  409. }
  410. Variant value = p_input.iter_get(iter, is_iter_get_valid);
  411. if (!is_iter_get_valid) {
  412. return "iter_get: not valid";
  413. }
  414. output.push_back(((int)value) + 5);
  415. } while (p_input.iter_next(iter, is_iter_next_valid));
  416. if (!is_iter_next_valid) {
  417. return "iter_next: not valid";
  418. }
  419. return output;
  420. }
  421. void Example::test_rpc(int p_value) {
  422. last_rpc_arg = p_value;
  423. }
  424. void Example::test_send_rpc(int p_value) {
  425. rpc("test_rpc", p_value);
  426. }
  427. int Example::return_last_rpc_arg() {
  428. return last_rpc_arg;
  429. }
  430. void Example::callable_bind() {
  431. Callable c = Callable(this, "emit_custom_signal").bind("bound", 11);
  432. c.call();
  433. }
  434. // Properties.
  435. void Example::set_custom_position(const Vector2 &pos) {
  436. custom_position = pos;
  437. }
  438. Vector2 Example::get_custom_position() const {
  439. return custom_position;
  440. }
  441. Vector4 Example::get_v4() const {
  442. return Vector4(1.2, 3.4, 5.6, 7.8);
  443. }
  444. // Virtual function override.
  445. bool Example::_has_point(const Vector2 &point) const {
  446. Label *label = get_node<Label>("Label");
  447. label->set_text("Got point: " + Variant(point).stringify());
  448. return false;
  449. }
  450. void Example::_input(const Ref<InputEvent> &event) {
  451. const InputEventKey *key_event = Object::cast_to<const InputEventKey>(*event);
  452. if (key_event) {
  453. emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode());
  454. }
  455. }