logic_nodes.js 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984
  1. /**
  2. * Copyright (C) 2014-2016 Triumph LLC
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /**
  18. * Created by dal on 04.09.15.
  19. */
  20. "use strict";
  21. /**
  22. * Logic Nodes scheduler module.
  23. * @name logic_nodes
  24. * @namespace
  25. * @exports exports as logic_nodes
  26. */
  27. b4w.module["__logic_nodes"] = function(exports, require) {
  28. var m_anim = require("__animation");
  29. var m_assets = require("__assets");
  30. var m_cam = require("__camera");
  31. var m_nla = require("__nla");
  32. var m_obj = require("__objects");
  33. var m_print = require("__print");
  34. var m_scs = require("__scenes");
  35. var m_cfg = require("__config");
  36. var m_ctl = require("__controls");
  37. var m_batch = require("__batch");
  38. var m_geom = require("__geometry");
  39. var m_mat3 = require("__mat3");
  40. var m_mat4 = require("__mat4");
  41. var m_phy = require("__physics");
  42. var m_quat = require("__quat");
  43. var m_sfx = require("__sfx");
  44. var m_time = require("__time");
  45. var m_trans = require("__transform");
  46. var m_tsr = require("__tsr");
  47. var m_util = require("__util");
  48. var m_vec3 = require("__vec3");
  49. var _vec4_tmp = new Float32Array(4);
  50. var _vec4_tmp1 = new Float32Array(4);
  51. var _vec3_tmp = new Float32Array(3);
  52. var _vec3_tmp1 = new Float32Array(3);
  53. var _vec2_tmp = new Float32Array(2);
  54. var _mat3_tmp = new Float32Array(9);
  55. var _mat4_tmp = new Float32Array(16);
  56. /**
  57. * Logic State
  58. */
  59. var UNINITIALIZED = 0;
  60. var INITIALIZATION = 1;
  61. var RUNNING = 2;
  62. var STOPPED = 3;
  63. var PAUSED = 4;
  64. /**
  65. * Node State by type
  66. */
  67. // Playing state(Animation, Transformation, Timeline, Sound etc)
  68. var NPS_NOT_STARTED = -1;
  69. var NPS_PLAYING = 0;
  70. var NPS_FINISHED = 1;
  71. // Switch Select
  72. var NSS_READY = -2;
  73. var NSS_NOT_READY = -1;
  74. var NSS_MISS = 0;
  75. var NSS_HIT = 1;
  76. // Send Request
  77. var NSR_NOT_STARTED = -1;
  78. var NSR_SENDING_REQUEST = 0;
  79. var NSR_RESPONSE_RECEIVED = 1;
  80. /**
  81. * Formats for convert_variable
  82. */
  83. var NT_NUMBER = 0;
  84. var NT_STRING = 1;
  85. exports.NT_NUMBER = NT_NUMBER;
  86. exports.NT_STRING = NT_STRING;
  87. /**
  88. * Keep node constants synchronized with:
  89. * exporter.py : process_scene_nla
  90. * reformer.js : assign_logic_nodes_object_params
  91. */
  92. /**
  93. * Node string operations
  94. */
  95. var NSO_JOIN = 0;
  96. var NSO_FIND = 1;
  97. var NSO_REPLACE = 2;
  98. var NSO_SPLIT = 3;
  99. var NSO_COMPARE = 4;
  100. exports.NSO_JOIN = NSO_JOIN;
  101. exports.NSO_FIND = NSO_FIND;
  102. exports.NSO_REPLACE = NSO_REPLACE;
  103. exports.NSO_SPLIT = NSO_SPLIT;
  104. exports.NSO_COMPARE = NSO_COMPARE;
  105. /**
  106. * Node json operations
  107. */
  108. var NJO_PARSE = 0;
  109. var NJO_ENCODE = 1;
  110. /**
  111. * Node conditions
  112. */
  113. var NC_GEQUAL = 0;
  114. var NC_LEQUAL = 1;
  115. var NC_GREATER = 2;
  116. var NC_LESS = 3;
  117. var NC_NOTEQUAL = 4;
  118. var NC_EQUAL = 5;
  119. exports.NC_GEQUAL = NC_GEQUAL;
  120. exports.NC_LEQUAL = NC_LEQUAL;
  121. exports.NC_GREATER = NC_GREATER;
  122. exports.NC_LESS = NC_LESS;
  123. exports.NC_NOTEQUAL = NC_NOTEQUAL;
  124. exports.NC_EQUAL = NC_EQUAL;
  125. /**
  126. * Node space type
  127. */
  128. var NST_WORLD = 0;
  129. var NST_PARENT = 1;
  130. var NST_LOCAL = 2;
  131. exports.NST_WORLD = NST_WORLD;
  132. exports.NST_PARENT = NST_PARENT;
  133. exports.NST_LOCAL = NST_LOCAL;
  134. /**
  135. * Node camera move style
  136. */
  137. var NCMS_STATIC = 0;
  138. var NCMS_TARGET = 1;
  139. var NCMS_EYE = 2;
  140. var NCMS_HOVER = 3;
  141. exports.NCMS_STATIC = NCMS_STATIC;
  142. exports.NCMS_TARGET = NCMS_TARGET;
  143. exports.NCMS_EYE = NCMS_EYE;
  144. exports.NCMS_HOVER = NCMS_HOVER;
  145. /**
  146. * Node cb param type
  147. */
  148. var NCPT_OBJECT = 0;
  149. var NCPT_VARIABLE = 1;
  150. exports.NCPT_OBJECT = NCPT_OBJECT;
  151. exports.NCPT_VARIABLE = NCPT_VARIABLE;
  152. /**
  153. * Add your node to _nodes_handlers
  154. * Use do_nothing_handler for stubs
  155. */
  156. var _nodes_handlers = {
  157. "ENTRYPOINT": entrypoint_handler,
  158. "HIDE": hide_object_handler,
  159. "SHOW": show_object_handler,
  160. "PAGEPARAM": pageparam_handler,
  161. "SWITCH_SELECT": switch_select_handler,
  162. "SELECT": select_handler,
  163. "PLAY": play_timeline_handler,
  164. "REDIRECT": redirect_handler,
  165. "MATH": math_handler,
  166. "CONDJUMP": conditional_jump_handler,
  167. "REGSTORE": regstore_handler,
  168. "PLAY_ANIM": play_anim_handler,
  169. "SELECT_PLAY": do_nothing_handler,
  170. "SEND_REQ": send_req_handler,
  171. "INHERIT_MAT": inherit_mat_handler,
  172. "SET_SHADER_NODE_PARAM": set_shader_node_param_handler,
  173. "DELAY": delay_handler,
  174. "APPLY_SHAPE_KEY": apply_shape_key_handler,
  175. "OUTLINE": outline_handler,
  176. "MOVE_CAMERA": move_camera_handler,
  177. "SET_CAMERA_MOVE_STYLE": set_camera_move_style_handler,
  178. "MOVE_TO": move_to_handler,
  179. "TRANSFORM_OBJECT": transform_object_handler,
  180. "SPEAKER_PLAY": speaker_play_handler,
  181. "SPEAKER_STOP": speaker_stop_handler,
  182. "STOP_ANIM": stop_anim_handler,
  183. "STOP_TIMELINE": stop_timeline_handler,
  184. "CONSOLE_PRINT": console_print_handler,
  185. "STRING": string_handler,
  186. "GET_TIMELINE": get_timeline_handler,
  187. "JSON": json_handler,
  188. "JS_CALLBACK": js_callback_handler,
  189. "EMPTY": do_nothing_handler
  190. };
  191. var _logic_arr = [];
  192. var _logic_custom_cb_arr = {};
  193. function init_node(snode, logic_script) {
  194. var node = {
  195. name: snode["name"],
  196. type: snode["type"],
  197. label: snode["label"],
  198. slot_idx_order: snode["slot_idx_order"],
  199. slot_idx_jump: snode["slot_idx_jump"],
  200. frame_start: snode["frame_range"][0],
  201. frame_end: snode["frame_range"][1],
  202. frame_start_mask: snode["frame_range_mask"] ? snode["frame_range_mask"][0] : true,
  203. frame_end_mask: snode["frame_range_mask"] ? snode["frame_range_mask"][1] : true,
  204. state: -1,
  205. sel_objs_len: -1,
  206. sel_obj_idx: -1,
  207. param_name: snode["param_name"],
  208. op: snode["operation"],
  209. mute: snode["mute"],
  210. dupli_name_list: snode["object"],
  211. obj: null,
  212. obj_state: null,
  213. camera_state: null,
  214. objects: {},
  215. anim_name: snode["anim_name"],
  216. anim_slot: m_anim.SLOT_ALL,
  217. parse_json_vars: snode["parse_json_vars"],
  218. parse_json_paths: snode["parse_json_paths"],
  219. objects_paths: snode["objects_paths"],
  220. nodes_paths: snode["nodes_paths"],
  221. floats: snode["floats"],
  222. bools: snode["bools"],
  223. vars: snode["variables"],
  224. strings: snode["strings"],
  225. materials_names: snode["materials_names"],
  226. shader_nd_type: snode["shader_nd_type"],
  227. common_usage_names: snode["common_usage_names"],
  228. encode_json_vars: snode["encode_json_vars"],
  229. encode_json_paths: snode["encode_json_paths"],
  230. thread: logic_script,
  231. process_node: _nodes_handlers[snode["type"]] ? _nodes_handlers[snode["type"]] : unknown_node_handler,
  232. processed: false,
  233. timer: 0,
  234. sel_obj_idxs: null,
  235. links_dict: snode["links"],
  236. links_idxs: []
  237. };
  238. return node;
  239. }
  240. function get_var(var_desc, global_vars, local_vars) {
  241. return var_desc[0]?global_vars[var_desc[1]]:local_vars[var_desc[1]];
  242. }
  243. function set_var(var_desc, global_vars, local_vars, value) {
  244. if (var_desc[0])
  245. global_vars[var_desc[1]] = value;
  246. else
  247. local_vars[var_desc[1]] = value;
  248. }
  249. function do_nothing_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  250. switch (logic.state) {
  251. case INITIALIZATION:
  252. break;
  253. case RUNNING:
  254. thread_state.curr_node = node.slot_idx_order;
  255. break;
  256. }
  257. }
  258. function unknown_node_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  259. switch (logic.state) {
  260. case INITIALIZATION:
  261. m_print.error("Unknown node type: " + node.type);
  262. break;
  263. case RUNNING:
  264. thread_state.curr_node = node.slot_idx_order;
  265. break;
  266. }
  267. }
  268. exports.init_logic = function(scene, data_id) {
  269. var logic = {
  270. data_id: data_id,
  271. scene_name: scene["name"],
  272. state: UNINITIALIZED,
  273. nla_thread: null,
  274. scene: scene,
  275. curr_thread: null,
  276. logic_threads: [],
  277. sorted_markers_values: [],
  278. variables: {}
  279. };
  280. scene._logic = logic;
  281. prepare_logic(scene, logic)
  282. };
  283. exports.update = function(timeline, elapsed) {
  284. var start_time = m_nla.get_start_time();
  285. if (start_time <= 0)
  286. return;
  287. // for each scene
  288. for (var i = 0; i < _logic_arr.length; i++) {
  289. process_logic(i, timeline, elapsed, start_time);
  290. }
  291. };
  292. exports.append_custom_cb = function(cb_id, cb) {
  293. _logic_custom_cb_arr[cb_id] = cb;
  294. }
  295. exports.remove_custom_cb = function(cb_id) {
  296. delete _logic_custom_cb_arr[cb_id];
  297. }
  298. exports.run_ep = function(scene_name, ep_name) {
  299. for (var i = 0; i < _logic_arr.length; i++) {
  300. if (_logic_arr[i].scene_name == scene_name) {
  301. var logic = _logic_arr[i];
  302. for (var j = 0; j < logic.logic_threads.length; j++) {
  303. var ep = logic.logic_threads[j].nodes[0];
  304. if (ep.name == ep_name) {
  305. if(ep.bools["js"])
  306. ep.mute = false;
  307. logic.logic_threads[j].thread_state.curr_node = 0;
  308. break;
  309. }
  310. }
  311. break;
  312. }
  313. }
  314. }
  315. function reset_play(thread) {
  316. var script = thread.nodes;
  317. for (var i = 0; i < script.length; i++) {
  318. var node = script[i];
  319. if (node.type == "PLAY")
  320. node.state = NPS_NOT_STARTED;
  321. }
  322. }
  323. function reset_selections(thread) {
  324. var script = thread.nodes;
  325. for (var i = 0; i < script.length; i++) {
  326. var node = script[i];
  327. if (node.type == "SWITCH_SELECT") {
  328. node.state = NSS_NOT_READY;
  329. }
  330. }
  331. }
  332. function process_logic(index, timeline, elapsed, start_time) {
  333. // for each thread
  334. var logic = _logic_arr[index];
  335. for (var k = 0; k < _logic_arr[index].logic_threads.length; k++) {
  336. logic.curr_thread = _logic_arr[index].logic_threads[k];
  337. process_logic_thread(_logic_arr[index].logic_threads[k], logic, timeline, elapsed, start_time);
  338. }
  339. }
  340. /**
  341. * Return URL param
  342. */
  343. function get_url_param(name, param_type, is_hash_param) {
  344. var cfg_url_params = m_cfg.get("url_params");
  345. if (cfg_url_params && name in cfg_url_params)
  346. return Number(cfg_url_params[name]);
  347. var url_params = is_hash_param ? location.hash : location.search;
  348. if (!url_params)
  349. return 0;
  350. var params = url_params.slice(1).split("&");
  351. for (var i = 0; i < params.length; i++) {
  352. var param = params[i].split("=");
  353. if (param.length > 1 && param[0] == name)
  354. return convert_variable(param[1], param_type);
  355. }
  356. return 0;
  357. }
  358. function get_object(node) {
  359. return m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.dupli_name_list || [], 0);
  360. }
  361. function get_world(node) {
  362. return m_obj.get_world_by_name(node.dupli_name_list[0], 0);
  363. }
  364. function entrypoint_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  365. switch (logic.state) {
  366. case RUNNING:
  367. thread_state.curr_node = node.slot_idx_order;
  368. break;
  369. }
  370. }
  371. function hide_object_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  372. switch (logic.state) {
  373. case INITIALIZATION:
  374. node.obj = get_object(node);
  375. if(!node.obj) {
  376. m_print.error("Logic script error: object not found. Node: ", node.name);
  377. node.mute = true;
  378. }
  379. break;
  380. case RUNNING:
  381. m_scs.change_visibility(node.obj, true);
  382. thread_state.curr_node = node.slot_idx_order;
  383. break;
  384. }
  385. }
  386. function show_object_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  387. switch (logic.state) {
  388. case INITIALIZATION:
  389. node.obj = get_object(node);
  390. if(!node.obj) {
  391. m_print.error("Logic script error: object not found. Node: ", node.name);
  392. node.mute = true;
  393. }
  394. break;
  395. case RUNNING:
  396. m_scs.change_visibility(node.obj, false);
  397. thread_state.curr_node = node.slot_idx_order;
  398. break;
  399. }
  400. }
  401. function pageparam_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  402. switch (logic.state) {
  403. case RUNNING:
  404. set_var(node.vars["vd"], logic.variables, thread_state.variables,
  405. get_url_param(node.param_name, node.floats["ptp"], node.bools["hsh"]));
  406. thread_state.curr_node = node.slot_idx_order;
  407. break;
  408. }
  409. }
  410. var gen_sel_cb = function() {
  411. return function (obj, id, pulse, param) {
  412. var node = param[0];
  413. var logic = param[1];
  414. var thread = param[2];
  415. for (var i = 0; i < node.sel_objs_len; i++) {
  416. if (m_ctl.get_sensor_value(obj, id, i) &&
  417. i == node.sel_obj_idx) {
  418. if (m_nla.is_play(logic._nla) && logic.nla_thread == node.thread)
  419. node.state = NSS_NOT_READY;
  420. else {
  421. if (!(thread.thread_state.in_progress && !node.bools["no_wait"]))
  422. node.state = NSS_HIT;
  423. }
  424. return;
  425. }
  426. }
  427. node.state = NSS_MISS;
  428. }
  429. };
  430. function create_select_sensor(node, logic, thread) {
  431. var obj = get_object(node);
  432. var sel_objs = m_obj.get_selectable_objects();
  433. var obj_idx = sel_objs.indexOf(obj);
  434. if (obj_idx == -1) {
  435. m_print.error("logic script error: non-selectable object:",
  436. node.dupli_name_list[node.dupli_name_list.length -1]);
  437. return -1;
  438. }
  439. node.state = NSS_NOT_READY;
  440. node.sel_objs_len = sel_objs.length;
  441. node.sel_obj_idx = obj_idx;
  442. var sel_sensors = [];
  443. for (var j = 0; j < sel_objs.length; j++) {
  444. sel_sensors.push(m_ctl.create_selection_sensor(sel_objs[j], false));
  445. }
  446. var select_cb = gen_sel_cb();
  447. m_ctl.create_sensor_manifold(obj, "LOGIC_NODES_SELECT_" + node.label, m_ctl.CT_SHOT,
  448. sel_sensors, m_ctl.default_OR_logic_fun, select_cb, [node, logic, thread]);
  449. }
  450. function select_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  451. switch (logic.state) {
  452. case INITIALIZATION:
  453. create_select_sensor(node, logic, logic.logic_threads[thread_state.thread_index]);
  454. break;
  455. case RUNNING:
  456. if (node.state == NSS_MISS || node.state == NSS_HIT) {
  457. thread_state.curr_node = node.state ? node.slot_idx_jump : node.slot_idx_order;
  458. node.state = NSS_NOT_READY;
  459. break;
  460. }
  461. if (node.bools["not_wait"]) {
  462. thread_state.curr_node = node.slot_idx_order;
  463. break;
  464. }
  465. break;
  466. }
  467. }
  468. var gen_switch_select_cb = function() {
  469. return function (obj, id, pulse, param) {
  470. var node = param[0];
  471. var logic = param[1];
  472. var thread = param[2];
  473. if (node.state != NSS_READY)
  474. return;
  475. for (var i = 0; i < node.sel_objs_len; i++) {
  476. var val = m_ctl.get_sensor_value(obj, id, i);
  477. if (val) {
  478. for (var j = 0; j < node.sel_obj_idxs.length; j++) {
  479. if (node.sel_obj_idxs[j] == i) {
  480. if (logic.nla_thread == node.thread) {
  481. if (m_nla.is_play(logic._nla))
  482. node.state = NSS_NOT_READY;
  483. if (!(thread.thread_state.in_progress)) {
  484. node.state = NSS_HIT;
  485. node.slot_idx_jump = node.links_idxs[j];
  486. }
  487. } else {
  488. node.state = NSS_HIT;
  489. node.slot_idx_jump = node.links_idxs[j];
  490. }
  491. return;
  492. }
  493. }
  494. }
  495. }
  496. node.state = NSS_MISS;
  497. }
  498. };
  499. function create_switch_select_sensor(node, logic, thread) {
  500. var sel_objs = m_obj.get_selectable_objects();
  501. node.sel_obj_idxs = [];
  502. node.links_idxs = [];
  503. for (var key in node.objects_paths) {
  504. var obj = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths[key], 0);
  505. var obj_idx = sel_objs.indexOf(obj);
  506. if (obj_idx == -1) {
  507. m_print.error("logic script error: non-selectable object:",
  508. node.objects_paths[key][node.objects_paths[key].length -1]);
  509. return -1;
  510. }
  511. node.sel_obj_idxs.push(obj_idx);
  512. node.links_idxs.push(node.links_dict[key]);
  513. }
  514. node.state = NSS_NOT_READY;
  515. node.sel_objs_len = sel_objs.length;
  516. var sel_sensors = [];
  517. for (var j = 0; j < sel_objs.length; j++) {
  518. sel_sensors.push(m_ctl.create_selection_sensor(sel_objs[j], false));
  519. }
  520. var select_cb = gen_switch_select_cb();
  521. m_ctl.create_sensor_manifold(obj, "LOGIC_NODES_SWITCH_SELECT_" + node.label, m_ctl.CT_SHOT,
  522. sel_sensors, m_ctl.default_OR_logic_fun, select_cb, [node, logic, thread]);
  523. }
  524. function switch_select_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  525. // state:
  526. // -1: not ready, needs sensor reset
  527. // -2: sensors are reset
  528. // 0: Miss
  529. // 1: Hit
  530. switch (logic.state) {
  531. case INITIALIZATION:
  532. create_switch_select_sensor(node, logic, logic.logic_threads[thread_state.thread_index]);
  533. break;
  534. case RUNNING:
  535. if (node.state == NSS_NOT_READY) {
  536. reset_selections(logic.logic_threads[thread_state.thread_index]);
  537. node.state = NSS_READY;
  538. }
  539. if (node.state == NSS_MISS || node.state == NSS_HIT) {
  540. thread_state.curr_node = node.state ? node.slot_idx_jump : node.slot_idx_order;
  541. node.state = NSS_NOT_READY;
  542. break;
  543. }
  544. break;
  545. }
  546. }
  547. function play_timeline_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  548. switch (logic.state) {
  549. case INITIALIZATION:
  550. m_nla.stop_nla();
  551. node.state = NPS_NOT_STARTED;
  552. if (!node.bools["not_wait"])
  553. node.bools["not_wait"] = false;
  554. break;
  555. case RUNNING:
  556. switch (node.state) {
  557. case NPS_NOT_STARTED:
  558. if (m_nla.is_play(logic._nla)) {
  559. // if current thread is in progress
  560. if (logic.curr_thread == logic.nla_thread && thread_state.in_progress) {
  561. break;
  562. }
  563. else {
  564. // reset nla thread
  565. var thread = logic.nla_thread;
  566. if (thread) {
  567. var nla_nd = thread.nodes[thread.thread_state.curr_node];
  568. thread.thread_state.curr_node = nla_nd.slot_idx_order;
  569. thread.nodes[thread.thread_state.curr_node].state = -1;
  570. reset_play(logic.nla_thread);
  571. }
  572. }
  573. }
  574. thread_state.in_progress = !node.bools["not_wait"];
  575. logic.nla_thread = logic.curr_thread;
  576. node.state = NPS_PLAYING;
  577. if (node.frame_start_mask) {
  578. m_nla.set_range_start(node.frame_start);
  579. m_nla.set_offset_from_range_start(timeline);
  580. }
  581. if (node.frame_end_mask) {
  582. m_nla.set_range_end(node.frame_end);
  583. } else {
  584. var cur_frame = m_nla.get_frame(timeline);
  585. var end = -1;
  586. for (var v in logic.sorted_markers_values) {
  587. if (cur_frame < logic.sorted_markers_values[v]) {
  588. end = v;
  589. break;
  590. }
  591. }
  592. if (end >= 0)
  593. m_nla.set_range_end(logic.sorted_markers_values[end]);
  594. else
  595. m_nla.set_range_end(m_nla.get_frame_end());
  596. }
  597. m_nla.play_nla(null);
  598. // if we can we must switch to the next node immediately
  599. // else there could be a conflict between nodes of such type
  600. if (node.bools["not_wait"]) {
  601. thread_state.curr_node = node.slot_idx_order;
  602. node.state = NPS_NOT_STARTED;
  603. thread_state.in_progress = false;
  604. }
  605. //
  606. break;
  607. case NPS_PLAYING:
  608. // playing
  609. if (!m_nla.is_play()) {
  610. thread_state.curr_node = node.slot_idx_order;
  611. node.state = NPS_NOT_STARTED;
  612. thread_state.in_progress = false;
  613. }
  614. break;
  615. case NPS_FINISHED:
  616. thread_state.curr_node = node.slot_idx_order;
  617. node.state = NPS_NOT_STARTED;
  618. logic.nla_thread = null;
  619. thread_state.in_progress = false;
  620. break;
  621. default:
  622. m_util.panic("Unknown state of " + node.name);
  623. node.state = NPS_NOT_STARTED;
  624. break;
  625. }
  626. break;
  627. }
  628. }
  629. function console_print_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  630. switch (logic.state) {
  631. case RUNNING:
  632. var vars = {};
  633. for (var i in node.vars) {
  634. var key = node.vars[i][1];
  635. vars[key] = get_var(node.vars[i], logic.variables, thread_state.variables);
  636. }
  637. m_print.log(node.common_usage_names["msg"], JSON.stringify(vars))
  638. thread_state.curr_node = node.slot_idx_order;
  639. break;
  640. }
  641. }
  642. function stop_timeline_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  643. switch (logic.state) {
  644. case RUNNING:
  645. if (node.bools["rst"]) {
  646. m_nla.set_offset_from_range_start(timeline);
  647. }
  648. m_nla.stop_nla();
  649. thread_state.curr_node = node.slot_idx_order;
  650. break;
  651. }
  652. }
  653. function redirect_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  654. switch (logic.state) {
  655. case RUNNING:
  656. var url = node.bools["url"] ? convert_variable(
  657. get_var(node.vars['url'], logic.variables, thread_state.variables), NT_STRING) : node.strings["url"];
  658. window.location.href = url;
  659. logic.state = STOPPED;
  660. break;
  661. }
  662. }
  663. function send_req_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  664. function asset_cb(loaded_data, uri, type, path, param) {
  665. var resp_string = JSON.stringify(loaded_data);
  666. set_var(param[0].vars["dst"], logic.variables, thread_state.variables, resp_string);
  667. param[0].state = 1;
  668. }
  669. switch (logic.state) {
  670. case RUNNING:
  671. switch (node.state) {
  672. case NSR_NOT_STARTED:
  673. node.state = NSR_SENDING_REQUEST;
  674. var url = node.bools["url"] ? convert_variable(
  675. get_var(node.vars['url'], logic.variables, thread_state.variables), NT_STRING) : node.strings["url"];
  676. var header = {};
  677. if (node.bools["ct"])
  678. header["Content-Type"] = node.strings["ct"];
  679. if (node.common_usage_names["request_type"] == "GET") {
  680. m_assets.enqueue([{id:url, type:m_assets.AT_JSON, url:url, overwrite_header: header,
  681. param:[node, thread_state.variables]}], asset_cb, null, null, null);
  682. }
  683. else if (node.common_usage_names["request_type"] == "POST") {
  684. var req = convert_variable(
  685. get_var(node.vars["dst1"], logic.variables, thread_state.variables), NT_STRING);
  686. m_assets.enqueue([{id:url, type:m_assets.AT_JSON, url:url, overwrite_header: header,
  687. request:"POST", post_type:m_assets.AT_JSON, post_data:req,
  688. param:[node, thread_state.variables]}], asset_cb, null, null, null);
  689. }
  690. break;
  691. case NSR_SENDING_REQUEST:
  692. break;
  693. case NSR_RESPONSE_RECEIVED:
  694. node.state = NSR_NOT_STARTED;
  695. thread_state.curr_node = node.slot_idx_order;
  696. break;
  697. }
  698. break;
  699. }
  700. }
  701. function inherit_mat_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  702. switch (logic.state) {
  703. case INITIALIZATION:
  704. for (var i = 0; i < 2; i++) {
  705. node.objects["id"+i] = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id"+i], 0);
  706. if(!node.objects["id"+i]) {
  707. m_print.error("Logic script error: object not found. Node: ", node.name);
  708. node.mute = true;
  709. }
  710. }
  711. break;
  712. case RUNNING:
  713. m_batch.inherit_material(node.objects['id0'], node.materials_names['id0'],
  714. node.objects['id1'], node.materials_names['id1']);
  715. thread_state.curr_node = node.slot_idx_order;
  716. break;
  717. }
  718. }
  719. function delay_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  720. switch (logic.state) {
  721. case INITIALIZATION:
  722. break;
  723. case RUNNING:
  724. if (node.state == NPS_NOT_STARTED) {
  725. // start delay
  726. node.state = NPS_PLAYING;
  727. node.timer = 0;
  728. thread_state.in_progress = true;
  729. return;
  730. } else if (node.state == NPS_PLAYING) {
  731. // count the time
  732. node.timer += elapsed;
  733. var dl = node.bools["dl"] ? convert_variable(
  734. get_var(node.vars['dl'], logic.variables,thread_state.variables), NT_NUMBER) : node.floats["dl"];
  735. if (dl < node.timer) {
  736. node.state = NPS_NOT_STARTED;
  737. thread_state.curr_node = node.slot_idx_order;
  738. thread_state.in_progress = false;
  739. }
  740. }
  741. break;
  742. }
  743. }
  744. function apply_shape_key_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  745. switch (logic.state) {
  746. case INITIALIZATION:
  747. var obj = node.objects["id0"] =
  748. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  749. if(!obj) {
  750. m_print.error("Logic script error: object not found. Node: ", node.name);
  751. node.mute = true;
  752. }
  753. var key = node.common_usage_names['sk'];
  754. if (!m_geom.check_shape_keys(obj)) {
  755. m_print.error("No shape keys in object:", obj.name);
  756. node.mute = true;
  757. } else if (!m_geom.has_shape_key(obj, key)) {
  758. m_print.error("Wrong key name:", key);
  759. node.mute = true;
  760. }
  761. break;
  762. case RUNNING:
  763. m_geom.apply_shape_key(node.objects["id0"], node.common_usage_names['sk'],
  764. node.bools["skv"] ? convert_variable(
  765. get_var(node.vars['skv'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats['skv']);
  766. thread_state.curr_node = node.slot_idx_order;
  767. break;
  768. }
  769. }
  770. function outline_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  771. switch (logic.state) {
  772. case INITIALIZATION:
  773. var obj = node.objects["id0"] =
  774. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  775. if(!obj) {
  776. m_print.error("Logic script error: object not found. Node: ", node.name);
  777. node.mute = true;
  778. }
  779. if (!(obj && obj.render && obj.render.outlining)) {
  780. m_print.error("Can't evaluate 'Outline' logic node: wrong object");
  781. node.mute = true;
  782. }
  783. break;
  784. case RUNNING:
  785. var obj = node.objects["id0"];
  786. switch (node.common_usage_names["outline_operation"]) {
  787. case "PLAY":
  788. var oa_set = obj.render.outline_anim_settings_default;
  789. m_obj.apply_outline_anim(obj, oa_set.outline_duration,
  790. oa_set.outline_period, oa_set.outline_relapses);
  791. break;
  792. case "STOP":
  793. m_obj.clear_outline_anim(obj);
  794. break;
  795. case "INTENSITY":
  796. obj.render.outline_intensity =
  797. node.bools["in"] ? convert_variable(
  798. get_var(node.vars['in'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats['in'];
  799. break;
  800. }
  801. thread_state.curr_node = node.slot_idx_order;
  802. break;
  803. }
  804. }
  805. function move_camera_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  806. function move_cam(cam, trans, target, tsr) {
  807. switch (m_cam.get_move_style(cam)) {
  808. case m_cam.MS_TARGET_CONTROLS:
  809. m_cam.set_trans_pivot(cam, trans, target);
  810. break;
  811. case m_cam.MS_EYE_CONTROLS:
  812. case m_cam.MS_STATIC:
  813. m_trans.set_tsr(cam, tsr);
  814. break;
  815. case m_cam.MS_HOVER_CONTROLS:
  816. m_vec3.sub(target, trans, _vec3_tmp);
  817. m_vec3.normalize(_vec3_tmp, _vec3_tmp);
  818. m_cam.set_hover_pivot(cam, target);
  819. var phi = 0;
  820. var theta = 0;
  821. // ZOX projection
  822. _vec3_tmp1[0] = _vec3_tmp[0];
  823. _vec3_tmp1[1] = 0;
  824. _vec3_tmp1[2] = _vec3_tmp[2];
  825. var dot = m_vec3.dot(_vec3_tmp1, _vec3_tmp);
  826. theta = Math.acos(dot / (m_vec3.length(_vec3_tmp1) * m_vec3.length(_vec3_tmp)));
  827. if (_vec3_tmp[2])
  828. phi = Math.atan(_vec3_tmp[0] / _vec3_tmp[2]);
  829. else {
  830. if (_vec3_tmp[0] > 0)
  831. phi = 0;
  832. else
  833. phi = Math.PI;
  834. }
  835. if (_vec3_tmp[2] > 0 && _vec3_tmp[0] > 0) {
  836. _vec2_tmp[1] = -(Math.PI + _vec2_tmp[1])
  837. }
  838. else if (_vec3_tmp[2] > 0 && _vec3_tmp[0] < 0) {
  839. _vec2_tmp[1] = -(Math.PI + _vec2_tmp[1]);
  840. }
  841. else if (_vec3_tmp[2] < 0 && _vec3_tmp[0] < 0) {
  842. _vec2_tmp[0] += Math.PI;
  843. phi = -(Math.PI - phi)
  844. }
  845. else if (_vec3_tmp[2] < 0 && _vec3_tmp[0] > 0) {
  846. _vec2_tmp[0] += Math.PI;
  847. phi -= Math.PI;
  848. }
  849. m_cam.rotate_hover_camera(cam, phi + Math.PI, -theta, true, true);
  850. break;
  851. }
  852. m_trans.update_transform(cam);
  853. m_phy.sync_transform(cam);
  854. }
  855. function set_tsr(cam, trans, target, tsr_out) {
  856. m_mat4.lookAt(trans, target, m_util.AXIS_Z, _mat4_tmp);
  857. m_mat4.invert(_mat4_tmp, _mat4_tmp);
  858. // m_mat4.rotateX(_mat4_tmp, Math.PI / 2, _mat4_tmp);
  859. var rot_matrix = _mat3_tmp;
  860. m_mat3.fromMat4(_mat4_tmp, rot_matrix);
  861. m_quat.fromMat3(rot_matrix, _vec4_tmp);
  862. m_quat.normalize(_vec4_tmp, _vec4_tmp);
  863. var scale = m_tsr.get_scale(cam.render.world_tsr);
  864. m_tsr.set_sep(trans, scale, _vec4_tmp, tsr_out);
  865. }
  866. switch (logic.state) {
  867. case INITIALIZATION:
  868. var o = null;
  869. o = node.objects["ca"] =
  870. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  871. if(!o) {
  872. m_print.error("Logic script error: object not found. Node: ", node.name);
  873. node.mute = true;
  874. }
  875. node.objects["tr"] =
  876. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id1"], 0);
  877. if(!node.objects["tr"]) {
  878. m_print.error("Logic script error: object not found. Node: ", node.name);
  879. node.mute = true;
  880. }
  881. node.objects["ta"] =
  882. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id2"], 0);
  883. if(!node.objects["ta"]) {
  884. m_print.error("Logic script error: object not found. Node: ", node.name);
  885. node.mute = true;
  886. }
  887. node.state = NPS_NOT_STARTED;
  888. node.camera_state = {
  889. trans_start: new Float32Array(3),
  890. trans_end: new Float32Array(3),
  891. interp_trans: new Float32Array(3),
  892. target_start: new Float32Array(3),
  893. target_end: new Float32Array(3),
  894. interp_target: new Float32Array(3),
  895. tsr_start: new Float32Array(8),
  896. tsr_end: new Float32Array(8),
  897. interp_tsr: new Float32Array(8)
  898. };
  899. break;
  900. case RUNNING:
  901. var cam = node.objects["ca"];
  902. var trans = m_tsr.get_trans_view(node.objects["tr"].render.world_tsr);
  903. var target = m_tsr.get_trans_view(node.objects["ta"].render.world_tsr);
  904. switch (node.state) {
  905. case NPS_NOT_STARTED:
  906. var dur = node.bools["dur"] ? convert_variable(
  907. get_var(node.vars['dur'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["dur"];
  908. if (dur == 0.0) {
  909. set_tsr(cam, trans, target, node.camera_state.tsr_end);
  910. move_cam(cam, trans, target, node.camera_state.tsr_end);
  911. thread_state.curr_node = node.slot_idx_order;
  912. return;
  913. }
  914. // start interpolation
  915. var cam_trans = m_tsr.get_trans_view(cam.render.world_tsr);
  916. m_vec3.copy(cam_trans, node.camera_state.trans_start);
  917. var move_style = m_cam.get_move_style(cam);
  918. if (move_style == m_cam.MS_HOVER_CONTROLS) {
  919. m_vec3.copy(cam.render.hover_pivot, node.camera_state.target_start);
  920. } else if (move_style == m_cam.MS_STATIC || move_style == m_cam.MS_EYE_CONTROLS) {
  921. // calc tsr
  922. m_tsr.copy(cam.render.world_tsr, node.camera_state.tsr_start);
  923. set_tsr(cam, trans, target, node.camera_state.tsr_end);
  924. } else {
  925. m_vec3.copy(cam.render.pivot, node.camera_state.target_start);
  926. }
  927. m_vec3.copy(trans, node.camera_state.trans_end);
  928. m_vec3.copy(target, node.camera_state.target_end);
  929. node.state = NPS_PLAYING;
  930. var trans_animator = m_time.animate(0, 1, dur * 1000, function(e) {
  931. if (m_scs.check_active()) {
  932. if (move_style == m_cam.MS_STATIC || move_style == m_cam.MS_EYE_CONTROLS) {
  933. m_tsr.interpolate(node.camera_state.tsr_start, node.camera_state.tsr_end,
  934. m_util.smooth_step(e), node.camera_state.interp_tsr);
  935. }
  936. else {
  937. node.camera_state.interp_target = m_vec3.lerp(node.camera_state.target_start,
  938. node.camera_state.target_end, m_util.smooth_step(e), node.camera_state.interp_target);
  939. node.camera_state.interp_trans = m_vec3.lerp(node.camera_state.trans_start,
  940. node.camera_state.trans_end, m_util.smooth_step(e), node.camera_state.interp_trans);
  941. }
  942. move_cam(cam, node.camera_state.interp_trans, node.camera_state.interp_target,
  943. node.camera_state.interp_tsr);
  944. if (e == 1)
  945. node.state = NPS_FINISHED;
  946. }
  947. });
  948. break;
  949. case NPS_PLAYING:
  950. // interpolation is in progress
  951. break;
  952. case NPS_FINISHED:
  953. // end
  954. m_time.clear_animation(trans_animator);
  955. node.state = NPS_NOT_STARTED;
  956. thread_state.curr_node = node.slot_idx_order;
  957. break;
  958. }
  959. break;
  960. }
  961. }
  962. function set_camera_move_style_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  963. switch (logic.state) {
  964. case INITIALIZATION:
  965. var cam = null;
  966. cam = node.objects["ca"] =
  967. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  968. if(!cam) {
  969. m_print.error("Logic script error: object not found. Node: ", node.name);
  970. node.mute = true;
  971. }
  972. var render = cam.render;
  973. node.cam_state = {
  974. target_cam_upside_down : render.target_cam_upside_down,
  975. use_panning : render.use_panning,
  976. horizontal_limits : render.horizontal_limits,
  977. vertical_limits : render.vertical_limits,
  978. distance_limits : render.distance_limits,
  979. hover_horiz_trans_limits : render.hover_horiz_trans_limits,
  980. hover_vert_trans_limits : render.hover_vert_trans_limits,
  981. pivot_limits : render.pivot_limits,
  982. enable_hover_hor_rotation : render.enable_hover_hor_rotation
  983. };
  984. break;
  985. case RUNNING:
  986. var cam = node.objects["ca"];
  987. var cam_render = cam.render;
  988. var cam_state = node.cam_state;
  989. m_cam.wipe_move_style(cam);
  990. switch (node.common_usage_names["camera_move_style"]) {
  991. case NCMS_STATIC:
  992. cam_render.move_style = m_cam.MS_STATIC;
  993. break;
  994. case NCMS_EYE:
  995. cam_render.move_style = m_cam.MS_EYE_CONTROLS;
  996. var pos = m_tsr.get_trans_view(cam_render.world_tsr);
  997. m_cam.setup_eye_model(cam, pos, null, cam_state.horizontal_limits, cam_state.vertical_limits);
  998. break;
  999. case NCMS_HOVER:
  1000. cam_render.move_style = m_cam.MS_HOVER_CONTROLS;
  1001. var pos = m_tsr.get_trans_view(cam_render.world_tsr);
  1002. var pivot = _vec3_tmp;
  1003. if (node.bools["pvo"]) {
  1004. var pvo = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id1"], 0);
  1005. pivot = m_tsr.get_trans_view(pvo.render.world_tsr);
  1006. }
  1007. else {
  1008. pivot[0] = node.bools["pvx"] ?
  1009. convert_variable(get_var(node.vars["pvx"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["pvx"];
  1010. pivot[1] = node.bools["pvy"] ?
  1011. convert_variable(get_var(node.vars["pvy"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["pvy"];
  1012. pivot[2] = node.bools["pvz"] ?
  1013. convert_variable(get_var(node.vars['pvz'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["pvz"];
  1014. }
  1015. m_cam.setup_hover_model(cam, pos, pivot, cam_state.distance_limits,
  1016. cam_state.vertical_limits, cam_state.hover_horiz_trans_limits, cam_state.hover_vert_trans_limits, cam_state.enable_hover_hor_rotation);
  1017. break;
  1018. case NCMS_TARGET:
  1019. cam_render.move_style = m_cam.MS_TARGET_CONTROLS;
  1020. var pos = m_tsr.get_trans_view(cam_render.world_tsr);
  1021. var pivot = _vec3_tmp;
  1022. if (node.bools["pvo"]) {
  1023. var pvo = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id1"], 0);
  1024. pivot = m_tsr.get_trans_view(pvo.render.world_tsr);
  1025. } else {
  1026. pivot[0] = node.bools["pvx"] ?
  1027. convert_variable(get_var(node.vars["pvx"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["pvx"];
  1028. pivot[1] = node.bools["pvy"] ?
  1029. convert_variable(get_var(node.vars["pvy"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["pvy"];
  1030. pivot[2] = node.bools["pvz"] ?
  1031. convert_variable(get_var(node.vars['pvz'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["pvz"];
  1032. }
  1033. m_cam.setup_target_model(cam, pos, pivot, cam_state.horizontal_limits,
  1034. cam_state.vertical_limits, cam_state.dist_limits, cam_state.pivot_limits, cam_state.use_panning);
  1035. break;
  1036. }
  1037. // velocities
  1038. var vel = _vec3_tmp1;
  1039. vel[0] = node.bools["vtr"] ?
  1040. convert_variable(get_var(node.vars["vtr"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["vtr"];
  1041. vel[1] = node.bools["vro"] ?
  1042. convert_variable(get_var(node.vars["vro"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["vro"];
  1043. vel[2] = node.bools["vzo"] ?
  1044. convert_variable(get_var(node.vars['vzo'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["vzo"];
  1045. vel[0] = m_util.clamp(vel[0], 0, Infinity);
  1046. vel[1] = m_util.clamp(vel[1], 0, Infinity);
  1047. vel[2] = m_util.clamp(vel[2], 0, 0.99);
  1048. cam_render.velocity_trans = vel[0];
  1049. cam_render.velocity_rot = vel[1];
  1050. cam_render.velocity_zoom = vel[2];
  1051. m_trans.update_transform(cam);
  1052. m_phy.sync_transform(cam);
  1053. // init ortho after the camera was updated
  1054. m_cam.init_ortho_props(cam);
  1055. thread_state.curr_node = node.slot_idx_order;
  1056. break;
  1057. }
  1058. }
  1059. function move_to_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1060. function move_to(obj, dest) {
  1061. m_trans.set_tsr(obj, dest);
  1062. m_trans.update_transform(obj);
  1063. m_phy.sync_transform(obj);
  1064. }
  1065. switch (logic.state) {
  1066. case INITIALIZATION:
  1067. node.objects["ob"] =
  1068. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  1069. if(!node.objects["ob"]) {
  1070. m_print.error("Logic script error: object not found. Node: ", node.name);
  1071. node.mute = true;
  1072. }
  1073. node.objects["de"] =
  1074. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id1"], 0);
  1075. if(!node.objects["de"]) {
  1076. m_print.error("Logic script error: object not found. Node: ", node.name);
  1077. node.mute = true;
  1078. }
  1079. node.state = NPS_NOT_STARTED;
  1080. node.obj_state = {
  1081. dest_tsr_start: new Float32Array(8),
  1082. dest_tsr_end: new Float32Array(8),
  1083. interp_tsr_dest: new Float32Array(8)
  1084. };
  1085. break;
  1086. case RUNNING:
  1087. var obj = node.objects["ob"];
  1088. m_tsr.copy(node.objects["ob"].render.world_tsr, node.obj_state.dest_tsr_start)
  1089. //destination
  1090. m_tsr.copy(node.objects["de"].render.world_tsr, node.obj_state.dest_tsr_end);
  1091. switch (node.state) {
  1092. case NPS_NOT_STARTED:
  1093. var dur = node.bools["dur"] ? convert_variable(
  1094. get_var(node.vars['dur'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["dur"];
  1095. if (dur == 0.0) {
  1096. move_to(obj, node.obj_state.dest_tsr_end);
  1097. thread_state.curr_node = node.slot_idx_order;
  1098. return;
  1099. }
  1100. node.state = NPS_PLAYING;
  1101. var trans_animator = m_time.animate(0, 1, dur * 1000, function(e) {
  1102. if (m_scs.check_active()) {
  1103. node.obj_state.interp_dest = m_tsr.interpolate(node.obj_state.dest_tsr_start,
  1104. node.obj_state.dest_tsr_end, m_util.smooth_step(e), node.obj_state.interp_tsr_dest);
  1105. move_to(obj, node.obj_state.interp_tsr_dest);
  1106. if (e == 1)
  1107. node.state = NPS_FINISHED;
  1108. }
  1109. });
  1110. break;
  1111. case NPS_PLAYING:
  1112. // interpolation is in progress
  1113. break;
  1114. case NPS_FINISHED:
  1115. // end
  1116. m_time.clear_animation(trans_animator);
  1117. node.state = NPS_NOT_STARTED;
  1118. thread_state.curr_node = node.slot_idx_order;
  1119. break;
  1120. }
  1121. break;
  1122. }
  1123. }
  1124. function transform_object_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1125. function transform_obj(obj, tsr, space) {
  1126. if(space == NST_WORLD){
  1127. m_trans.set_tsr(obj, tsr);
  1128. }
  1129. else {
  1130. m_trans.set_tsr_rel(obj, tsr);
  1131. }
  1132. m_trans.update_transform(obj);
  1133. m_phy.sync_transform(obj);
  1134. }
  1135. switch (logic.state) {
  1136. case INITIALIZATION:
  1137. node.objects["ob"] =
  1138. m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  1139. if(!node.objects["ob"]) {
  1140. m_print.error("Logic script error: object not found. Node: ", node.name);
  1141. node.mute = true;
  1142. }
  1143. node.state = NPS_NOT_STARTED;
  1144. node.obj_state = {
  1145. space: NST_WORLD,
  1146. tsr_start: new Float32Array(8),
  1147. tsr_end: new Float32Array(8),
  1148. interp_tsr: new Float32Array(8)
  1149. };
  1150. break;
  1151. case RUNNING:
  1152. var obj = node.objects["ob"];
  1153. switch (node.state) {
  1154. case NPS_NOT_STARTED:
  1155. var tr = _vec3_tmp1;
  1156. tr[0] = node.bools["trx"] ?
  1157. convert_variable(get_var(node.vars['trx'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["trx"];
  1158. tr[1] = node.bools["try"] ?
  1159. convert_variable(get_var(node.vars['try'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["try"];
  1160. tr[2] = node.bools["trz"] ?
  1161. convert_variable(get_var(node.vars['trz'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["trz"];
  1162. //euler angles rotation
  1163. var eul_rot = _vec3_tmp
  1164. eul_rot[0] = node.bools["rox"] ?
  1165. convert_variable(get_var(node.vars['rox'], logic.variables, thread_state.variables), NT_NUMBER) * Math.PI / 180 : node.floats["rox"];
  1166. eul_rot[1] = node.bools["roy"] ?
  1167. convert_variable(get_var(node.vars['roy'], logic.variables, thread_state.variables), NT_NUMBER) * Math.PI / 180 : node.floats["roy"];
  1168. eul_rot[2] = node.bools["roz"] ?
  1169. convert_variable(get_var(node.vars['roz'], logic.variables, thread_state.variables), NT_NUMBER) * Math.PI / 180 : node.floats["roz"];
  1170. var sc = node.bools["sc"] ? get_var(node.vars['sc'], logic.variables, thread_state.variables) : node.floats["sc"]
  1171. m_util.euler_to_quat(eul_rot, _vec4_tmp);
  1172. m_tsr.set_sep(
  1173. tr,
  1174. sc,
  1175. _vec4_tmp,
  1176. node.obj_state.tsr_end
  1177. );
  1178. node.obj_state.space = node.common_usage_names["space_type"];
  1179. switch (node.obj_state.space) {
  1180. case NST_WORLD:
  1181. m_trans.get_tsr(obj, node.obj_state.tsr_start);
  1182. break;
  1183. case NST_PARENT:
  1184. m_trans.get_tsr_rel(obj, node.obj_state.tsr_start);
  1185. break;
  1186. case NST_LOCAL:
  1187. m_trans.get_tsr_rel(obj, node.obj_state.tsr_start);
  1188. m_tsr.multiply(node.obj_state.tsr_start, node.obj_state.tsr_end, node.obj_state.tsr_end)
  1189. break;
  1190. }
  1191. var dur = node.bools["dur"] ?
  1192. convert_variable(get_var(node.vars['dur'], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["dur"];
  1193. if (dur == 0.0) {
  1194. transform_obj(obj, node.obj_state.tsr_end, node.obj_state.space);
  1195. thread_state.curr_node = node.slot_idx_order;
  1196. return;
  1197. }
  1198. node.state = NPS_PLAYING;
  1199. var trans_animator = m_time.animate(0, 1, dur * 1000, function(e) {
  1200. if (m_scs.check_active()) {
  1201. m_tsr.interpolate(node.obj_state.tsr_start, node.obj_state.tsr_end,
  1202. m_util.smooth_step(e), node.obj_state.interp_tsr);
  1203. transform_obj(obj, node.obj_state.interp_tsr, node.obj_state.space);
  1204. if (e == 1)
  1205. node.state = NPS_FINISHED;
  1206. }
  1207. });
  1208. break;
  1209. case NPS_PLAYING:
  1210. // interpolation is in progress
  1211. break;
  1212. case NPS_FINISHED:
  1213. // end
  1214. m_time.clear_animation(trans_animator);
  1215. node.state = NPS_NOT_STARTED;
  1216. thread_state.curr_node = node.slot_idx_order;
  1217. break;
  1218. }
  1219. break;
  1220. }
  1221. }
  1222. function speaker_play_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1223. switch (logic.state) {
  1224. case INITIALIZATION:
  1225. node.obj = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  1226. if(!node.obj) {
  1227. m_print.error("Logic script error: object not found. Node: ", node.name);
  1228. node.mute = true;
  1229. }
  1230. if (node.bools["not_wait"] == undefined)
  1231. node.bools["not_wait"] = true;
  1232. break;
  1233. case RUNNING:
  1234. if (!m_sfx.is_playing(node.obj)) {
  1235. if (node.state == NPS_PLAYING)
  1236. node.state = NPS_FINISHED;
  1237. }
  1238. switch (node.state) {
  1239. case NPS_NOT_STARTED:
  1240. // this node is not playing
  1241. // check other threads
  1242. for (var k in logic.logic_threads) {
  1243. var curr_node = logic.logic_threads[k].thread_state.curr_node;
  1244. if (curr_node != -1) { // case when the thread is already stopped
  1245. var node2 = logic.logic_threads[k].nodes[curr_node];
  1246. if (node2.type == "SPEAKER_PLAY" && node2!= node && node2.state == NPS_PLAYING && node2.obj == node.obj)
  1247. node2.state = NPS_FINISHED;
  1248. }
  1249. }
  1250. // blocking selection
  1251. if (!node.bools["not_wait"])
  1252. thread_state.in_progress = true;
  1253. m_sfx.play_def(node.obj);
  1254. node.state = NPS_PLAYING;
  1255. break;
  1256. case NPS_PLAYING:
  1257. // playing
  1258. if (node.bools["not_wait"]) {
  1259. thread_state.curr_node = node.slot_idx_order;
  1260. node.state = NPS_NOT_STARTED;
  1261. }
  1262. break;
  1263. case NPS_FINISHED:
  1264. // end playing
  1265. if (!node.bools["not_wait"])
  1266. thread_state.in_progress = false;
  1267. thread_state.curr_node = node.slot_idx_order;
  1268. node.state = NPS_NOT_STARTED;
  1269. break;
  1270. default:
  1271. m_util.panic("Unknown state of " + node.name);
  1272. node.state = NPS_NOT_STARTED;
  1273. break;
  1274. }
  1275. }
  1276. }
  1277. function speaker_stop_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1278. switch (logic.state) {
  1279. case INITIALIZATION:
  1280. node.obj = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  1281. if(!node.obj) {
  1282. m_print.error("Logic script error: object not found. Node: ", node.name);
  1283. node.mute = true;
  1284. }
  1285. break;
  1286. case RUNNING:
  1287. m_sfx.stop(node.obj);
  1288. thread_state.curr_node = node.slot_idx_order;
  1289. break;
  1290. }
  1291. }
  1292. function set_shader_node_param_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1293. switch (logic.state) {
  1294. case INITIALIZATION:
  1295. if (node.objects_paths["id0"]) {
  1296. node.objects["id0"] = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths["id0"], 0);
  1297. if(!node.objects_paths["id0"]) {
  1298. m_print.error("Logic script error: object not found. Node: ", node.name);
  1299. node.mute = true;
  1300. }
  1301. node.nodes_paths["id0"].unshift(node.materials_names["id0"])
  1302. }
  1303. break;
  1304. case RUNNING:
  1305. var obj = node.objects["id0"];
  1306. var name_list = node.nodes_paths["id0"]
  1307. var mat_name = name_list[0];
  1308. var batch_main = m_batch.find_batch_material(obj, mat_name, "MAIN");
  1309. thread_state.curr_node = node.slot_idx_order;
  1310. if (batch_main === null) {
  1311. m_print.error("Material \"" + mat_name +
  1312. "\" was not found in the object \"" + obj.name + "\".");
  1313. return;
  1314. }
  1315. if (node.shader_nd_type == "ShaderNodeRGB") {
  1316. var ind = m_batch.get_node_ind_by_name_list(batch_main.node_rgb_inds,
  1317. name_list);
  1318. m_batch.set_nodemat_rgb(obj, mat_name, ind,
  1319. node.bools["id0"] ?
  1320. convert_variable(get_var(node.vars["id0"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["id0"],
  1321. node.bools["id1"] ?
  1322. convert_variable(get_var(node.vars["id1"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["id1"],
  1323. node.bools["id2"] ?
  1324. convert_variable(get_var(node.vars["id2"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["id2"]);
  1325. }
  1326. if (node.shader_nd_type == "ShaderNodeValue") {
  1327. var ind = m_batch.get_node_ind_by_name_list(batch_main.node_value_inds,
  1328. name_list);
  1329. m_batch.set_nodemat_value(obj, mat_name, ind,
  1330. node.bools["id0"] ?
  1331. convert_variable(get_var(node.vars["id0"], logic.variables, thread_state.variables), NT_NUMBER) : node.floats["id0"]);
  1332. }
  1333. break;
  1334. }
  1335. }
  1336. function math_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1337. switch (logic.state) {
  1338. case RUNNING:
  1339. var val1 = (node.vars["v1"][1] == -1) ? node.floats["inp1"] : convert_variable(
  1340. get_var(node.vars["v1"], logic.variables, thread_state.variables), NT_NUMBER);
  1341. var val2 = (node.vars["v2"][1] == -1) ? node.floats["inp2"] : convert_variable(
  1342. get_var(node.vars["v2"], logic.variables, thread_state.variables), NT_NUMBER);
  1343. var result = 0;
  1344. switch (node.op) {
  1345. case "ADD":
  1346. result = val1 + val2;
  1347. break;
  1348. case "MUL":
  1349. result = val1 * val2;
  1350. break;
  1351. case "SUB":
  1352. result = val1 - val2;
  1353. break;
  1354. case "DIV":
  1355. if (val2 == 0)
  1356. m_util.panic("Division by zero in Logic script");
  1357. result = val1 / val2;
  1358. break;
  1359. case "RAND":
  1360. result = Math.random() * (val2 - val1) + val1;
  1361. break;
  1362. }
  1363. set_var(node.vars["vd"], logic.variables, thread_state.variables, result);
  1364. thread_state.curr_node = node.slot_idx_order;
  1365. break;
  1366. }
  1367. }
  1368. function conditional_jump_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1369. switch (logic.state) {
  1370. case RUNNING:
  1371. var arg_type = node.bools["str"] ? NT_STRING : NT_NUMBER;
  1372. var arg_arr = node.bools["str"] ? node.strings : node.floats;
  1373. var val1 = (node.vars["v1"][1] == -1) ? arg_arr["inp1"] : convert_variable(
  1374. get_var(node.vars["v1"], logic.variables, thread_state.variables), arg_type);
  1375. var val2 = (node.vars["v2"][1] == -1) ? arg_arr["inp2"] : convert_variable(
  1376. get_var(node.vars["v2"], logic.variables, thread_state.variables), arg_type);
  1377. var cond_result = false;
  1378. switch (node.common_usage_names["condition"]) {
  1379. case NC_EQUAL:
  1380. if (val1 == val2)
  1381. cond_result = true;
  1382. break;
  1383. case NC_NOTEQUAL:
  1384. if (val1 != val2)
  1385. cond_result = true;
  1386. break;
  1387. case NC_LESS:
  1388. if (val1 < val2)
  1389. cond_result = true;
  1390. break;
  1391. case NC_GREATER:
  1392. if (val1 > val2)
  1393. cond_result = true;
  1394. break;
  1395. case NC_LEQUAL:
  1396. if (val1 <= val2)
  1397. cond_result = true;
  1398. break;
  1399. case NC_GEQUAL:
  1400. if (val1 >= val2)
  1401. cond_result = true;
  1402. break;
  1403. }
  1404. if (cond_result)
  1405. thread_state.curr_node = node.slot_idx_jump;
  1406. else
  1407. thread_state.curr_node = node.slot_idx_order;
  1408. break;
  1409. }
  1410. }
  1411. function regstore_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1412. switch (logic.state) {
  1413. case RUNNING:
  1414. var arg_arr = node.common_usage_names["variable_type"] == NT_STRING ? node.strings : node.floats;
  1415. set_var([node.bools["gl"] || node.vars["vd"][0], node.vars["vd"][1]], logic.variables, thread_state.variables, arg_arr["inp1"]);
  1416. thread_state.curr_node = node.slot_idx_order;
  1417. break;
  1418. }
  1419. }
  1420. function play_anim_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1421. // return anim slot number for already applied, -1 otherwise
  1422. function get_slot_by_anim_name(obj, anim_name) {
  1423. var anim_slot = -1;
  1424. for (var i = 0; i < 8; i++) {
  1425. var anim_slot_obj = obj.anim_slots[i];
  1426. if (anim_slot_obj && anim_slot_obj.animation_name) {
  1427. if (m_anim.strip_baked_suffix(anim_slot_obj.animation_name) == m_anim.strip_baked_suffix(anim_name))
  1428. if (anim_slot != -1)
  1429. anim_slot = i;
  1430. else
  1431. return -1;
  1432. }
  1433. }
  1434. return anim_slot;
  1435. }
  1436. switch (logic.state) {
  1437. case INITIALIZATION:
  1438. node.obj = node.bools["env"] ? get_world(node) : get_object(node);
  1439. if(!node.obj) {
  1440. m_print.error("Logic script error: object not found. Node: ", node.name);
  1441. node.mute = true;
  1442. }
  1443. break;
  1444. case RUNNING:
  1445. if (node.state == NPS_PLAYING && !m_anim.is_play(node.obj, node.anim_slot))
  1446. node.state = NPS_FINISHED;
  1447. switch (node.state) {
  1448. case NPS_NOT_STARTED:
  1449. // this node is not playing
  1450. // check other threads
  1451. for (var k in logic.logic_threads) {
  1452. var curr_node = logic.logic_threads[k].thread_state.curr_node;
  1453. if (curr_node != -1) { // case when the thread is already stopped
  1454. var node2 = logic.logic_threads[k].nodes[curr_node];
  1455. if (node2.type == "PLAY_ANIM" && node2 != node && node2.state == NPS_PLAYING && node2.obj == node.obj)
  1456. node2.state = NPS_FINISHED;
  1457. }
  1458. }
  1459. var behavior = node.common_usage_names["param_anim_behavior"];
  1460. if (node.anim_name == "") {
  1461. // TODO make check_anim for default animation
  1462. m_anim.apply_def(node.obj);
  1463. m_anim.set_behavior(node.obj, behavior, m_anim.SLOT_ALL);
  1464. } else {
  1465. var anim_slot = get_slot_by_anim_name(node.obj, node.anim_name);
  1466. if (anim_slot == -1) {
  1467. node.anim_slot = m_anim.slot_by_anim_type(node.obj, node.anim_name);
  1468. m_anim.apply(node.obj, null, node.anim_name, node.anim_slot);
  1469. } else
  1470. node.anim_slot = anim_slot;
  1471. m_anim.set_behavior(node.obj, behavior, node.anim_slot);
  1472. }
  1473. // blocking selection
  1474. if (!node.bools["not_wait"])
  1475. thread_state.in_progress = true;
  1476. m_anim.play(node.obj, null, node.anim_slot);
  1477. node.state = NPS_PLAYING;
  1478. // if we can we must switch to the next node immediately
  1479. // else there could be a conflict between nodes of such type
  1480. if (node.bools["not_wait"]) {
  1481. thread_state.curr_node = node.slot_idx_order;
  1482. node.state = NPS_NOT_STARTED;
  1483. }
  1484. break;
  1485. case NPS_PLAYING:
  1486. // playing
  1487. // do nothing
  1488. break;
  1489. case NPS_FINISHED:
  1490. // end playing
  1491. if (!node.bools["not_wait"])
  1492. thread_state.in_progress = false;
  1493. thread_state.curr_node = node.slot_idx_order;
  1494. node.state = NPS_NOT_STARTED;
  1495. break;
  1496. default:
  1497. m_util.panic("Unknown state of " + node.name);
  1498. node.state = NPS_NOT_STARTED;
  1499. break;
  1500. }
  1501. break;
  1502. }
  1503. }
  1504. function stop_anim_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1505. switch (logic.state) {
  1506. case INITIALIZATION:
  1507. node.obj = node.bools["env"] ? get_world(node) : get_object(node);
  1508. if(!node.obj) {
  1509. m_print.error("Logic script error: object not found. Node: ", node.name);
  1510. node.mute = true;
  1511. }
  1512. break;
  1513. case RUNNING:
  1514. m_anim.stop(node.obj, m_anim.SLOT_ALL);
  1515. if (node.bools["rst"])
  1516. m_anim.set_first_frame(node.obj, m_anim.SLOT_ALL);
  1517. thread_state.curr_node = node.slot_idx_order;
  1518. break;
  1519. }
  1520. }
  1521. function string_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1522. switch (logic.state) {
  1523. case RUNNING:
  1524. var op1 = node.bools["id0"] ? convert_variable(
  1525. get_var(node.vars['id0'], logic.variables, thread_state.variables), NT_STRING) : node.strings["id0"];
  1526. var op2 = node.bools["id1"] ? convert_variable(
  1527. get_var(node.vars['id1'], logic.variables, thread_state.variables), NT_STRING) : node.strings["id1"];
  1528. var result = 0;
  1529. switch (node.common_usage_names["string_operation"]) {
  1530. case NSO_JOIN:
  1531. result = op1 + op2;
  1532. break;
  1533. case NSO_FIND:
  1534. result = op1.indexOf(op2);
  1535. break;
  1536. case NSO_REPLACE:
  1537. var op3 = node.bools["id2"] ? convert_variable(
  1538. get_var(node.vars['id2'], logic.variables, thread_state.variables), NT_STRING) : node.strings["id2"];
  1539. result = op1.replace(op2, op3);
  1540. break;
  1541. case NSO_SPLIT:
  1542. var vars = node.vars;
  1543. result = op1.substring(0, op1.indexOf(op2));
  1544. set_var(vars['dst1'], logic.variables, thread_state.variables,
  1545. op1.substring(op1.indexOf(op2)+1, op1.length))
  1546. //if splitter not found keep result in main destination
  1547. if(get_var(vars['dst'], logic.variables, thread_state.variables) == "") {
  1548. result = get_var(vars['dst1'], logic.variables, thread_state.variables);
  1549. set_var(vars['dst1'], logic.variables, thread_state.variables, "");
  1550. }
  1551. break;
  1552. case NSO_COMPARE:
  1553. switch (node.common_usage_names["condition"]) {
  1554. case NC_EQUAL:
  1555. result = op1 == op2 ? 1 : 0;
  1556. break;
  1557. case NC_NOTEQUAL:
  1558. result = op1 != op2 ? 1 : 0;
  1559. break;
  1560. case NC_LESS:
  1561. result = op1 < op2 ? 1 : 0;
  1562. break;
  1563. case NC_GREATER:
  1564. result = op1 > op2 ? 1 : 0;
  1565. break;
  1566. case NC_LEQUAL:
  1567. result = op1 <= op2 ? 1 : 0;
  1568. break;
  1569. case NC_GEQUAL:
  1570. result = op1 >= op2 ? 1 : 0;
  1571. break;
  1572. }
  1573. break;
  1574. }
  1575. set_var(node.vars['dst'], logic.variables, thread_state.variables, result);
  1576. thread_state.curr_node = node.slot_idx_order;
  1577. break;
  1578. }
  1579. }
  1580. function get_timeline_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1581. switch (logic.state) {
  1582. case RUNNING:
  1583. var curr_frame = node.bools["nla"] ? convert_variable(m_nla.get_frame(timeline), NT_NUMBER)
  1584. : convert_variable(m_time.get_frame(timeline), NT_NUMBER);
  1585. set_var(node.vars["vd"], logic.variables, thread_state.variables, curr_frame);
  1586. thread_state.curr_node = node.slot_idx_order;
  1587. break;
  1588. }
  1589. }
  1590. function json_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1591. function get_json_deep_values(src_json, parse_paths, parse_vars, dest_vars) {
  1592. for(var i = 0; i < parse_paths.length; i++) {
  1593. var full_path = parse_paths[i];
  1594. var path_steps = full_path.split('.');
  1595. var deep_value = src_json;
  1596. var dest_name = parse_vars[i];
  1597. for(var j = 0; j < path_steps.length; j++) {
  1598. deep_value = deep_value[path_steps[j]];
  1599. if(deep_value === undefined || deep_value === null)
  1600. break;
  1601. }
  1602. deep_value = convert_b4w_type(deep_value);
  1603. dest_vars[dest_name] = deep_value;
  1604. }
  1605. }
  1606. function encode_json_deep_values(src_vars, encode_paths, encode_vars, dest_json) {
  1607. if(!dest_json)
  1608. dest_json = {};
  1609. for(var i = 0; i < encode_paths.length; i++) {
  1610. var full_path = encode_paths[i];
  1611. var path_steps = full_path.split('.');
  1612. var deep_value = dest_json;
  1613. var src_name = encode_vars[i];
  1614. if (!src_name in src_vars)
  1615. continue;
  1616. for(var j = 0; j < path_steps.length - 1; j++) {
  1617. if(deep_value[path_steps[j]] === undefined)
  1618. if (isNaN(path_steps[j+1]))
  1619. deep_value[path_steps[j]] = {};
  1620. else
  1621. deep_value[path_steps[j]] = [];
  1622. deep_value = deep_value[path_steps[j]];
  1623. }
  1624. var last_path_step = path_steps[path_steps.length -1];
  1625. deep_value[last_path_step] = convert_b4w_type(src_vars[src_name]);
  1626. }
  1627. }
  1628. switch (logic.state) {
  1629. case RUNNING:
  1630. switch (node.common_usage_names["json_operation"]) {
  1631. case"PARSE":
  1632. //JSON parsing errors shield
  1633. try {
  1634. var src_json_string = convert_variable(get_var(node.vars["jsn"], logic.variables, thread_state.variables), NT_STRING);
  1635. var src_json = JSON.parse(src_json_string);
  1636. get_json_deep_values(src_json, node.parse_json_paths, node.parse_json_vars, thread_state.variables);
  1637. } catch(e) {
  1638. m_print.error("logic script error: non valid JSON string");
  1639. }
  1640. break;
  1641. case "ENCODE":
  1642. var dest_json = {};
  1643. encode_json_deep_values(thread_state.variables, node.encode_json_paths, node.encode_json_vars, dest_json);
  1644. var dest_json_string = convert_variable(JSON.stringify(dest_json), NT_STRING);
  1645. set_var(node.vars["jsn"], logic.variables, thread_state.variables, dest_json_string);
  1646. break;
  1647. }
  1648. thread_state.curr_node = node.slot_idx_order;
  1649. break;
  1650. }
  1651. }
  1652. function js_callback_handler(node, logic, thread_state, timeline, elapsed, start_time) {
  1653. switch (logic.state) {
  1654. case RUNNING:
  1655. var cb_id = node.bools["cb"] ? convert_variable(
  1656. get_var(node.vars["cb"], logic.variables, thread_state.variables), NT_STRING) : node.strings["cb"];
  1657. var in_params = [];
  1658. var index = 0;
  1659. var key = "id" + index;
  1660. var param;
  1661. var in_types_dict = node.common_usage_names["js_cb_params"];
  1662. while (key in in_types_dict) {
  1663. if (in_types_dict[key] == NCPT_OBJECT)
  1664. param = m_obj.get_object(m_obj.GET_OBJECT_BY_DUPLI_NAME_LIST, node.objects_paths[key], 0);
  1665. else
  1666. param = get_var(node.vars[key], logic.variables, thread_state.variables);
  1667. in_params.push(param);
  1668. index++;
  1669. key = "id" + index;
  1670. }
  1671. var out_params = [];
  1672. index = 0;
  1673. key = "out" + index;
  1674. while (key in node.vars) {
  1675. param = get_var(node.vars[key], logic.variables, thread_state.variables);
  1676. out_params.push(param);
  1677. index++;
  1678. key = "out" + index;
  1679. }
  1680. var ret = 1;
  1681. if (cb_id in _logic_custom_cb_arr) {
  1682. ret = !_logic_custom_cb_arr[cb_id](in_params, out_params);
  1683. if (ret) {
  1684. for (var i = 0; i < out_params.length; i++) {
  1685. key = "out" + i;
  1686. if (key in node.vars)
  1687. set_var(node.vars[key], logic.variables, thread_state.variables, convert_b4w_type(out_params[i]));
  1688. }
  1689. }
  1690. } else
  1691. m_print.error("logic script error: no custom callback with id " + cb_id);
  1692. if (ret)
  1693. thread_state.curr_node = node.slot_idx_order;
  1694. break;
  1695. }
  1696. }
  1697. function process_logic_thread(thread, logic, timeline, elapsed, start_time) {
  1698. var script = thread.nodes;
  1699. if (!script.length)
  1700. return;
  1701. /* Reset "processed"*/
  1702. for (var i = 0; i < script.length; i++) {
  1703. script[i].processed = false
  1704. }
  1705. for (var i = 0; i < script.length; i++) {
  1706. if (thread.thread_state.curr_node >= 0)
  1707. var node = script[thread.thread_state.curr_node];
  1708. else
  1709. return;
  1710. if (node.processed)
  1711. return;
  1712. if (!node.mute) {
  1713. node.process_node(node, logic, thread.thread_state, timeline, elapsed, start_time);
  1714. node.processed = true;
  1715. } else {
  1716. if (node.type == "ENTRYPOINT") {
  1717. return;
  1718. } else {
  1719. thread.thread_state.curr_node = node.slot_idx_order;
  1720. node.processed = true;
  1721. continue;
  1722. }
  1723. }
  1724. }
  1725. }
  1726. function prepare_logic(scene, logic) {
  1727. var bpy_logic_threads = scene["b4w_logic_nodes"];
  1728. var logic_threads = logic.logic_threads;
  1729. logic.state = INITIALIZATION;
  1730. for (var k = 0; k < bpy_logic_threads.length; k++) {
  1731. var thread = {
  1732. nodes: [],
  1733. thread_state: {
  1734. scene: scene,
  1735. curr_node: 0,
  1736. in_progress: false, // used for selection blocking during Play Anim
  1737. // in cases when "Do Not Wait" is not checked
  1738. // or during Delay
  1739. thread_index: k,
  1740. variables: {
  1741. "R1": 0,
  1742. "R2": 0,
  1743. "R3": 0,
  1744. "R4": 0,
  1745. "R5": 0,
  1746. "R6": 0,
  1747. "R7": 0,
  1748. "R8": 0
  1749. }
  1750. }
  1751. };
  1752. logic_threads.push(thread);
  1753. var logic_script = logic_threads[logic_threads.length - 1];
  1754. var subtree = bpy_logic_threads[k];
  1755. for (var i = 0; i < subtree.length; i++) {
  1756. var snode = subtree[i];
  1757. var node = init_node(snode, logic_script);
  1758. // just copy all
  1759. logic_script.nodes.push(node);
  1760. }
  1761. for (var l = 0; l < logic_script.nodes.length; l++) {
  1762. node = logic_script.nodes[l];
  1763. // NOTE: additional checks for objects inside node handlers
  1764. // are for objects from non-exported scenes and other difficult to prevent stuff
  1765. if(!node.mute)
  1766. node.process_node(node, logic, thread.thread_state, 0, 0);
  1767. }
  1768. }
  1769. var markers = scene["timeline_markers"];
  1770. for (var key in markers) {
  1771. logic.sorted_markers_values.push(markers[key]);
  1772. }
  1773. function sortNumber(a,b)
  1774. {
  1775. return a - b;
  1776. }
  1777. logic.sorted_markers_values.sort(sortNumber);
  1778. logic.state = RUNNING;
  1779. _logic_arr.push(logic)
  1780. }
  1781. function convert_variable(variable, type) {
  1782. switch (type) {
  1783. case NT_NUMBER:
  1784. return Boolean(Number(variable)) ? Number(variable) : 0;
  1785. case NT_STRING:
  1786. return String(variable);
  1787. default:
  1788. return null;
  1789. }
  1790. }
  1791. function convert_b4w_type(variable) {
  1792. switch (typeof(variable)) {
  1793. case "string":
  1794. return convert_variable(variable, NT_STRING);
  1795. case "number":
  1796. return convert_variable(variable, NT_NUMBER);
  1797. default:
  1798. return convert_variable(variable, NT_STRING);
  1799. }
  1800. }
  1801. exports.cleanup = function() {
  1802. _logic_arr.length = 0;
  1803. _logic_custom_cb_arr = {};
  1804. }
  1805. }