visual_instance.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*************************************************************************/
  2. /* visual_instance.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 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 "visual_instance.h"
  31. #include "baked_light_instance.h"
  32. #include "room_instance.h"
  33. #include "scene/scene_string_names.h"
  34. #include "servers/visual_server.h"
  35. #include "skeleton.h"
  36. AABB VisualInstance::get_transformed_aabb() const {
  37. return get_global_transform().xform(get_aabb());
  38. }
  39. void VisualInstance::_notification(int p_what) {
  40. switch (p_what) {
  41. case NOTIFICATION_ENTER_WORLD: {
  42. // CHECK ROOM
  43. Spatial *parent = get_parent_spatial();
  44. Room *room = NULL;
  45. bool is_geom = cast_to<GeometryInstance>();
  46. while (parent) {
  47. room = parent->cast_to<Room>();
  48. if (room)
  49. break;
  50. if (is_geom && parent->cast_to<BakedLightSampler>()) {
  51. VS::get_singleton()->instance_geometry_set_baked_light_sampler(get_instance(), parent->cast_to<BakedLightSampler>()->get_instance());
  52. break;
  53. }
  54. parent = parent->get_parent_spatial();
  55. }
  56. if (room) {
  57. VisualServer::get_singleton()->instance_set_room(instance, room->get_instance());
  58. }
  59. // CHECK SKELETON => moving skeleton attaching logic to MeshInstance
  60. /*
  61. Skeleton *skeleton=get_parent()?get_parent()->cast_to<Skeleton>():NULL;
  62. if (skeleton)
  63. VisualServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() );
  64. */
  65. VisualServer::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
  66. } break;
  67. case NOTIFICATION_TRANSFORM_CHANGED: {
  68. Transform gt = get_global_transform();
  69. VisualServer::get_singleton()->instance_set_transform(instance, gt);
  70. } break;
  71. case NOTIFICATION_EXIT_WORLD: {
  72. VisualServer::get_singleton()->instance_set_scenario(instance, RID());
  73. VisualServer::get_singleton()->instance_set_room(instance, RID());
  74. VisualServer::get_singleton()->instance_attach_skeleton(instance, RID());
  75. VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID());
  76. } break;
  77. }
  78. }
  79. RID VisualInstance::get_instance() const {
  80. return instance;
  81. }
  82. RID VisualInstance::_get_visual_instance_rid() const {
  83. return instance;
  84. }
  85. void VisualInstance::set_layer_mask(uint32_t p_mask) {
  86. layers = p_mask;
  87. VisualServer::get_singleton()->instance_set_layer_mask(instance, p_mask);
  88. }
  89. uint32_t VisualInstance::get_layer_mask() const {
  90. return layers;
  91. }
  92. void VisualInstance::_bind_methods() {
  93. ObjectTypeDB::bind_method(_MD("_get_visual_instance_rid"), &VisualInstance::_get_visual_instance_rid);
  94. ObjectTypeDB::bind_method(_MD("set_base", "base"), &VisualInstance::set_base);
  95. ObjectTypeDB::bind_method(_MD("set_layer_mask", "mask"), &VisualInstance::set_layer_mask);
  96. ObjectTypeDB::bind_method(_MD("get_layer_mask"), &VisualInstance::get_layer_mask);
  97. ObjectTypeDB::bind_method(_MD("get_transformed_aabb"), &VisualInstance::get_transformed_aabb);
  98. ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_ALL_FLAGS), _SCS("set_layer_mask"), _SCS("get_layer_mask"));
  99. }
  100. void VisualInstance::set_base(const RID &p_base) {
  101. VisualServer::get_singleton()->instance_set_base(instance, p_base);
  102. }
  103. VisualInstance::VisualInstance() {
  104. instance = VisualServer::get_singleton()->instance_create();
  105. VisualServer::get_singleton()->instance_attach_object_instance_ID(instance, get_instance_ID());
  106. layers = 1;
  107. }
  108. VisualInstance::~VisualInstance() {
  109. VisualServer::get_singleton()->free(instance);
  110. }
  111. void GeometryInstance::set_material_override(const Ref<Material> &p_material) {
  112. material_override = p_material;
  113. VS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
  114. }
  115. Ref<Material> GeometryInstance::get_material_override() const {
  116. return material_override;
  117. }
  118. void GeometryInstance::set_draw_range_begin(float p_dist) {
  119. draw_begin = p_dist;
  120. VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), draw_begin, draw_end);
  121. }
  122. float GeometryInstance::get_draw_range_begin() const {
  123. return draw_begin;
  124. }
  125. void GeometryInstance::set_draw_range_end(float p_dist) {
  126. draw_end = p_dist;
  127. VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), draw_begin, draw_end);
  128. }
  129. float GeometryInstance::get_draw_range_end() const {
  130. return draw_end;
  131. }
  132. void GeometryInstance::_notification(int p_what) {
  133. if (p_what == NOTIFICATION_ENTER_WORLD) {
  134. if (flags[FLAG_USE_BAKED_LIGHT]) {
  135. _find_baked_light();
  136. }
  137. _update_visibility();
  138. } else if (p_what == NOTIFICATION_EXIT_WORLD) {
  139. if (flags[FLAG_USE_BAKED_LIGHT]) {
  140. if (baked_light_instance) {
  141. baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed, this, SceneStringNames::get_singleton()->_baked_light_changed);
  142. baked_light_instance = NULL;
  143. }
  144. _baked_light_changed();
  145. }
  146. }
  147. if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
  148. _update_visibility();
  149. }
  150. }
  151. void GeometryInstance::_baked_light_changed() {
  152. if (!baked_light_instance)
  153. VS::get_singleton()->instance_geometry_set_baked_light(get_instance(), RID());
  154. else
  155. VS::get_singleton()->instance_geometry_set_baked_light(get_instance(), baked_light_instance->get_baked_light_instance());
  156. }
  157. void GeometryInstance::_find_baked_light() {
  158. Node *n = get_parent();
  159. while (n) {
  160. BakedLightInstance *bl = n->cast_to<BakedLightInstance>();
  161. if (bl) {
  162. baked_light_instance = bl;
  163. baked_light_instance->connect(SceneStringNames::get_singleton()->baked_light_changed, this, SceneStringNames::get_singleton()->_baked_light_changed);
  164. _baked_light_changed();
  165. return;
  166. }
  167. n = n->get_parent();
  168. }
  169. _baked_light_changed();
  170. }
  171. void GeometryInstance::_update_visibility() {
  172. if (!is_inside_tree())
  173. return;
  174. _change_notify("geometry/visible");
  175. VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_VISIBLE, is_visible() && flags[FLAG_VISIBLE]);
  176. }
  177. void GeometryInstance::set_flag(Flags p_flag, bool p_value) {
  178. ERR_FAIL_INDEX(p_flag, FLAG_MAX);
  179. if (p_flag == FLAG_CAST_SHADOW) {
  180. if (p_value == true) {
  181. set_cast_shadows_setting(SHADOW_CASTING_SETTING_ON);
  182. } else {
  183. set_cast_shadows_setting(SHADOW_CASTING_SETTING_OFF);
  184. }
  185. }
  186. if (flags[p_flag] == p_value)
  187. return;
  188. flags[p_flag] = p_value;
  189. VS::get_singleton()->instance_geometry_set_flag(get_instance(), (VS::InstanceFlags)p_flag, p_value);
  190. if (p_flag == FLAG_VISIBLE) {
  191. _update_visibility();
  192. }
  193. if (p_flag == FLAG_USE_BAKED_LIGHT) {
  194. if (is_inside_world()) {
  195. if (!p_value) {
  196. if (baked_light_instance) {
  197. baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed, this, SceneStringNames::get_singleton()->_baked_light_changed);
  198. baked_light_instance = NULL;
  199. }
  200. _baked_light_changed();
  201. } else {
  202. _find_baked_light();
  203. }
  204. }
  205. }
  206. }
  207. bool GeometryInstance::get_flag(Flags p_flag) const {
  208. ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
  209. if (p_flag == FLAG_CAST_SHADOW) {
  210. if (shadow_casting_setting == SHADOW_CASTING_SETTING_OFF) {
  211. return false;
  212. } else {
  213. return true;
  214. }
  215. }
  216. return flags[p_flag];
  217. }
  218. void GeometryInstance::set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting) {
  219. shadow_casting_setting = p_shadow_casting_setting;
  220. VS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (VS::ShadowCastingSetting)p_shadow_casting_setting);
  221. }
  222. GeometryInstance::ShadowCastingSetting GeometryInstance::get_cast_shadows_setting() const {
  223. return shadow_casting_setting;
  224. }
  225. void GeometryInstance::set_baked_light_texture_id(int p_id) {
  226. baked_light_texture_id = p_id;
  227. VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(), baked_light_texture_id);
  228. }
  229. int GeometryInstance::get_baked_light_texture_id() const {
  230. return baked_light_texture_id;
  231. }
  232. void GeometryInstance::set_extra_cull_margin(float p_margin) {
  233. ERR_FAIL_COND(p_margin < 0);
  234. extra_cull_margin = p_margin;
  235. VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin);
  236. }
  237. float GeometryInstance::get_extra_cull_margin() const {
  238. return extra_cull_margin;
  239. }
  240. void GeometryInstance::_bind_methods() {
  241. ObjectTypeDB::bind_method(_MD("set_material_override", "material"), &GeometryInstance::set_material_override);
  242. ObjectTypeDB::bind_method(_MD("get_material_override"), &GeometryInstance::get_material_override);
  243. ObjectTypeDB::bind_method(_MD("set_flag", "flag", "value"), &GeometryInstance::set_flag);
  244. ObjectTypeDB::bind_method(_MD("get_flag", "flag"), &GeometryInstance::get_flag);
  245. ObjectTypeDB::bind_method(_MD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance::set_cast_shadows_setting);
  246. ObjectTypeDB::bind_method(_MD("get_cast_shadows_setting"), &GeometryInstance::get_cast_shadows_setting);
  247. ObjectTypeDB::bind_method(_MD("set_draw_range_begin", "mode"), &GeometryInstance::set_draw_range_begin);
  248. ObjectTypeDB::bind_method(_MD("get_draw_range_begin"), &GeometryInstance::get_draw_range_begin);
  249. ObjectTypeDB::bind_method(_MD("set_draw_range_end", "mode"), &GeometryInstance::set_draw_range_end);
  250. ObjectTypeDB::bind_method(_MD("get_draw_range_end"), &GeometryInstance::get_draw_range_end);
  251. ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id", "id"), &GeometryInstance::set_baked_light_texture_id);
  252. ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id);
  253. ObjectTypeDB::bind_method(_MD("set_extra_cull_margin", "margin"), &GeometryInstance::set_extra_cull_margin);
  254. ObjectTypeDB::bind_method(_MD("get_extra_cull_margin"), &GeometryInstance::get_extra_cull_margin);
  255. ObjectTypeDB::bind_method(_MD("get_aabb"), &GeometryInstance::get_aabb);
  256. ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed);
  257. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"), FLAG_VISIBLE);
  258. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "geometry/material_override", PROPERTY_HINT_RESOURCE_TYPE, "Material"), _SCS("set_material_override"), _SCS("get_material_override"));
  259. ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), _SCS("set_cast_shadows_setting"), _SCS("get_cast_shadows_setting"));
  260. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/receive_shadows"), _SCS("set_flag"), _SCS("get_flag"), FLAG_RECEIVE_SHADOWS);
  261. ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/range_begin", PROPERTY_HINT_RANGE, "0,32768,0.01"), _SCS("set_draw_range_begin"), _SCS("get_draw_range_begin"));
  262. ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/range_end", PROPERTY_HINT_RANGE, "0,32768,0.01"), _SCS("set_draw_range_end"), _SCS("get_draw_range_end"));
  263. ADD_PROPERTY(PropertyInfo(Variant::REAL, "geometry/extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0"), _SCS("set_extra_cull_margin"), _SCS("get_extra_cull_margin"));
  264. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/billboard"), _SCS("set_flag"), _SCS("get_flag"), FLAG_BILLBOARD);
  265. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"), FLAG_BILLBOARD_FIX_Y);
  266. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"), FLAG_DEPH_SCALE);
  267. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/visible_in_all_rooms"), _SCS("set_flag"), _SCS("get_flag"), FLAG_VISIBLE_IN_ALL_ROOMS);
  268. ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "geometry/use_baked_light"), _SCS("set_flag"), _SCS("get_flag"), FLAG_USE_BAKED_LIGHT);
  269. ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry/baked_light_tex_id"), _SCS("set_baked_light_texture_id"), _SCS("get_baked_light_texture_id"));
  270. // ADD_SIGNAL( MethodInfo("visibility_changed"));
  271. BIND_CONSTANT(FLAG_VISIBLE);
  272. BIND_CONSTANT(FLAG_CAST_SHADOW);
  273. BIND_CONSTANT(FLAG_RECEIVE_SHADOWS);
  274. BIND_CONSTANT(FLAG_BILLBOARD);
  275. BIND_CONSTANT(FLAG_BILLBOARD_FIX_Y);
  276. BIND_CONSTANT(FLAG_DEPH_SCALE);
  277. BIND_CONSTANT(FLAG_VISIBLE_IN_ALL_ROOMS);
  278. BIND_CONSTANT(FLAG_MAX);
  279. BIND_CONSTANT(SHADOW_CASTING_SETTING_OFF);
  280. BIND_CONSTANT(SHADOW_CASTING_SETTING_ON);
  281. BIND_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
  282. BIND_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);
  283. }
  284. GeometryInstance::GeometryInstance() {
  285. draw_begin = 0;
  286. draw_end = 0;
  287. for (int i = 0; i < FLAG_MAX; i++) {
  288. flags[i] = false;
  289. }
  290. flags[FLAG_VISIBLE] = true;
  291. flags[FLAG_CAST_SHADOW] = true;
  292. flags[FLAG_RECEIVE_SHADOWS] = true;
  293. shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
  294. baked_light_instance = NULL;
  295. baked_light_texture_id = 0;
  296. extra_cull_margin = 0;
  297. VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(), 0);
  298. }