ui_view2d.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. let ui_view2d_pipe: gpu_pipeline_t;
  2. let ui_view2d_channel_loc: i32;
  3. let ui_view2d_text_input_hover: bool = false;
  4. let ui_view2d_uvmap_show: bool = false;
  5. let ui_view2d_tex_type: paint_tex_t = paint_tex_t.BASE;
  6. let ui_view2d_layer_mode: view_2d_layer_mode_t = view_2d_layer_mode_t.SELECTED;
  7. let ui_view2d_type: view_2d_type_t = view_2d_type_t.LAYER;
  8. let ui_view2d_show: bool = false;
  9. let ui_view2d_wx: i32;
  10. let ui_view2d_wy: i32;
  11. let ui_view2d_ww: i32;
  12. let ui_view2d_wh: i32;
  13. let ui_view2d_hwnd: ui_handle_t = ui_handle_create();
  14. let ui_view2d_pan_x: f32 = 0.0;
  15. let ui_view2d_pan_y: f32 = 0.0;
  16. let ui_view2d_pan_scale: f32 = 1.0;
  17. let ui_view2d_tiled_show: bool = false;
  18. let ui_view2d_controls_down: bool = false;
  19. let _ui_view2d_render_tex: gpu_texture_t;
  20. let _ui_view2d_render_x: f32;
  21. let _ui_view2d_render_y: f32;
  22. let _ui_view2d_render_tw: f32;
  23. let _ui_view2d_render_th: f32;
  24. let ui_view2d_grid: gpu_texture_t = null;
  25. let ui_view2d_grid_redraw: bool = true;
  26. let ui_view2d_htab: ui_handle_t = ui_handle_create();
  27. function ui_view2d_init() {
  28. ui_view2d_pipe = gpu_create_pipeline();
  29. ui_view2d_pipe.vertex_shader = sys_get_shader("layer_view.vert");
  30. ui_view2d_pipe.fragment_shader = sys_get_shader("layer_view.frag");
  31. let vs: gpu_vertex_structure_t = {};
  32. gpu_vertex_struct_add(vs, "pos", gpu_vertex_data_t.F32_2X);
  33. ui_view2d_pipe.input_layout = vs;
  34. ui_view2d_pipe.blend_source = gpu_blend_t.ONE;
  35. ui_view2d_pipe.blend_destination = gpu_blend_t.ZERO;
  36. ARRAY_ACCESS(ui_view2d_pipe.color_write_mask_alpha, 0) = false;
  37. gpu_pipeline_compile(ui_view2d_pipe);
  38. pipes_offset = 0;
  39. pipes_get_constant_location("float4");
  40. pipes_get_constant_location("float4");
  41. pipes_get_constant_location("float4");
  42. ui_view2d_channel_loc = pipes_get_constant_location("int");
  43. }
  44. function ui_view2d_draw_image(image: gpu_texture_t, dx: f32, dy: f32, dw: f32, dh: f32, channel: i32) {
  45. if (ui_view2d_type == view_2d_type_t.LAYER) {
  46. gpu_set_int(ui_view2d_channel_loc, channel);
  47. }
  48. draw_scaled_image(image, dx, dy, dw, dh);
  49. }
  50. function ui_view2d_render() {
  51. ui_view2d_ww = config_raw.layout[layout_size_t.NODES_W];
  52. ui_view2d_wx = math_floor(sys_w()) + ui_toolbar_w(true);
  53. ui_view2d_wy = 0;
  54. if (!ui_base_show) {
  55. ui_view2d_ww += config_raw.layout[layout_size_t.SIDEBAR_W] + ui_toolbar_w(true);
  56. ui_view2d_wx -= ui_toolbar_w(true);
  57. }
  58. if (!base_view3d_show) {
  59. ui_view2d_ww += base_view3d_w();
  60. }
  61. if (!ui_view2d_show) {
  62. return;
  63. }
  64. if (context_raw.pdirty >= 0) {
  65. ui_view2d_hwnd.redraws = 2; // Paint was active
  66. }
  67. // Cache grid
  68. if (ui_view2d_grid_redraw) {
  69. if (ui_view2d_grid != null) {
  70. gpu_delete_texture(ui_view2d_grid);
  71. }
  72. ui_view2d_grid = ui_nodes_draw_grid(ui_view2d_pan_scale);
  73. ui_view2d_grid_redraw = false;
  74. }
  75. // Ensure UV map is drawn
  76. if (ui_view2d_uvmap_show) {
  77. util_uv_cache_uv_map();
  78. }
  79. // Ensure font image is drawn
  80. if (context_raw.font.image == null) {
  81. util_render_make_font_preview();
  82. }
  83. ui_begin(ui);
  84. let headerh: i32 = config_raw.layout[layout_size_t.HEADER] == 1 ? ui_header_h * 2 : ui_header_h;
  85. let apph: i32 = iron_window_height() - config_raw.layout[layout_size_t.STATUS_H] + headerh;
  86. if (!base_view3d_show) {
  87. apph = base_h();
  88. }
  89. ui_view2d_wh = iron_window_height() - config_raw.layout[layout_size_t.STATUS_H];
  90. if (ui_nodes_show) {
  91. ui_view2d_wh -= config_raw.layout[layout_size_t.NODES_H];
  92. if (config_raw.touch_ui) {
  93. ui_view2d_wh += ui_header_h;
  94. }
  95. }
  96. if (!base_view3d_show && ui_nodes_show) {
  97. ui_view2d_wx = 0;
  98. ui_view2d_ww = base_view3d_w();
  99. ui_view2d_wh = iron_window_height() - config_raw.layout[layout_size_t.STATUS_H];
  100. }
  101. if (ui_window(ui_view2d_hwnd, ui_view2d_wx, ui_view2d_wy, ui_view2d_ww, ui_view2d_wh)) {
  102. let expand: bool = !base_view3d_show && !ui_nodes_show && config_raw.layout[layout_size_t.SIDEBAR_W] == 0;
  103. ui_tab(ui_view2d_htab, expand ? tr("2D View") + " " : tr("2D View"), false, -1, !base_view3d_show);
  104. if (ui_tab(ui_view2d_htab, tr("+"))) {
  105. ui_view2d_htab.i = 0;
  106. }
  107. // Grid
  108. // draw_set_color(0xffffffff);
  109. // let step: f32 = ui_nodes_grid_cell_w * ui_view2d_pan_scale;
  110. // let x: f32 = math_fmod(ui_view2d_pan_x, step) - step;
  111. // let y: f32 = math_fmod(ui_view2d_pan_y, step) - step;
  112. // draw_image(ui_view2d_grid, x, y);
  113. draw_set_color(ui.ops.theme.SEPARATOR_COL + 0x00020202);
  114. draw_filled_rect(0, 0, ui_view2d_ww, ui_view2d_wh);
  115. draw_set_color(0xffffffff);
  116. // Texture
  117. let tex: gpu_texture_t = null;
  118. let l: slot_layer_t = context_raw.layer;
  119. let channel: i32 = 0;
  120. let tw: f32 = ui_view2d_ww * 0.95 * ui_view2d_pan_scale;
  121. let tx: f32 = ui_view2d_ww / 2 - tw / 2 + ui_view2d_pan_x;
  122. let ty: f32 = apph / 2 - tw / 2 + ui_view2d_pan_y;
  123. if (ui_view2d_type == view_2d_type_t.ASSET) {
  124. tex = project_get_image(context_raw.texture);
  125. }
  126. else if (ui_view2d_type == view_2d_type_t.NODE) {
  127. let nodes: ui_nodes_t = ui_nodes_get_nodes();
  128. let c: ui_node_canvas_t = ui_nodes_get_canvas(true);
  129. if (nodes.nodes_selected_id.length > 0) {
  130. let sel: ui_node_t = ui_get_node(c.nodes, nodes.nodes_selected_id[0]);
  131. let img: gpu_texture_t = ui_nodes_get_node_preview_image(sel);
  132. if (img != null) {
  133. tex = ui_nodes_get_node_preview_image(sel);
  134. }
  135. }
  136. }
  137. else if (ui_view2d_type == view_2d_type_t.LAYER) {
  138. let layer: slot_layer_t = l;
  139. if (config_raw.brush_live && render_path_paint_live_layer_drawn > 0) {
  140. layer = render_path_paint_live_layer;
  141. }
  142. if (context_raw.tool == tool_type_t.MATERIAL) {
  143. layer = render_path_paint_live_layer;
  144. }
  145. if (ui_view2d_layer_mode == view_2d_layer_mode_t.VISIBLE) {
  146. let current: gpu_texture_t = _draw_current;
  147. let in_use: bool = gpu_in_use;
  148. if (in_use)
  149. draw_end();
  150. layer = layers_flatten();
  151. if (in_use)
  152. draw_begin(current);
  153. }
  154. else if (slot_layer_is_group(layer)) {
  155. let current: gpu_texture_t = _draw_current;
  156. let in_use: bool = gpu_in_use;
  157. if (in_use)
  158. draw_end();
  159. layer = layers_flatten(false, slot_layer_get_children(layer));
  160. if (in_use)
  161. draw_begin(current);
  162. }
  163. tex = slot_layer_is_mask(context_raw.layer) ? layer.texpaint
  164. : ui_view2d_tex_type == paint_tex_t.BASE ? layer.texpaint
  165. : ui_view2d_tex_type == paint_tex_t.OPACITY ? layer.texpaint
  166. : ui_view2d_tex_type == paint_tex_t.NORMAL ? layer.texpaint_nor
  167. : layer.texpaint_pack;
  168. channel = slot_layer_is_mask(context_raw.layer) ? 1
  169. : ui_view2d_tex_type == paint_tex_t.OCCLUSION ? 1
  170. : ui_view2d_tex_type == paint_tex_t.ROUGHNESS ? 2
  171. : ui_view2d_tex_type == paint_tex_t.METALLIC ? 3
  172. : ui_view2d_tex_type == paint_tex_t.OPACITY ? 4
  173. : ui_view2d_tex_type == paint_tex_t.HEIGHT ? 4
  174. : ui_view2d_tex_type == paint_tex_t.NORMAL ? 5
  175. : 0;
  176. }
  177. else if (ui_view2d_type == view_2d_type_t.FONT) {
  178. tex = context_raw.font.image;
  179. }
  180. let th: f32 = tw;
  181. if (tex != null) {
  182. th = tw * (tex.height / tex.width);
  183. ty = apph / 2 - th / 2 + ui_view2d_pan_y;
  184. if (ui_view2d_type == view_2d_type_t.LAYER) {
  185. draw_set_pipeline(ui_view2d_pipe);
  186. }
  187. ui_view2d_draw_image(tex, tx, ty, tw, th, channel);
  188. if (ui_view2d_tiled_show) {
  189. ui_view2d_draw_image(tex, tx - tw, ty, tw, th, channel);
  190. ui_view2d_draw_image(tex, tx - tw, ty - th, tw, th, channel);
  191. ui_view2d_draw_image(tex, tx - tw, ty + th, tw, th, channel);
  192. ui_view2d_draw_image(tex, tx + tw, ty, tw, th, channel);
  193. ui_view2d_draw_image(tex, tx + tw, ty - th, tw, th, channel);
  194. ui_view2d_draw_image(tex, tx + tw, ty + th, tw, th, channel);
  195. ui_view2d_draw_image(tex, tx, ty - th, tw, th, channel);
  196. ui_view2d_draw_image(tex, tx, ty + th, tw, th, channel);
  197. }
  198. if (ui_view2d_type == view_2d_type_t.LAYER) {
  199. draw_set_pipeline(null);
  200. }
  201. // Texture and node preview color picking
  202. if ((context_in_2d_view(view_2d_type_t.ASSET) || context_in_2d_view(view_2d_type_t.NODE)) && context_raw.tool == tool_type_t.PICKER &&
  203. ui.input_down) {
  204. _ui_view2d_render_tex = tex;
  205. _ui_view2d_render_x = ui.input_x - tx - ui_view2d_wx;
  206. ;
  207. _ui_view2d_render_y = ui.input_y - ty - ui_view2d_wy;
  208. _ui_view2d_render_tw = tw;
  209. _ui_view2d_render_th = th;
  210. sys_notify_on_next_frame(function() {
  211. let rt: render_target_t = map_get(render_path_render_targets, "texpaint_picker");
  212. let texpaint_picker: gpu_texture_t = rt._image;
  213. draw_begin(texpaint_picker);
  214. draw_scaled_image(_ui_view2d_render_tex, -_ui_view2d_render_x, -_ui_view2d_render_y, _ui_view2d_render_tw, _ui_view2d_render_th);
  215. draw_end();
  216. let a: buffer_t = gpu_get_texture_pixels(texpaint_picker);
  217. /// if IRON_BGRA
  218. let i0: i32 = 2;
  219. let i1: i32 = 1;
  220. let i2: i32 = 0;
  221. /// else
  222. let i0: i32 = 0;
  223. let i1: i32 = 1;
  224. let i2: i32 = 2;
  225. /// end
  226. context_raw.picked_color.base = color_set_rb(context_raw.picked_color.base, buffer_get_u8(a, i0));
  227. context_raw.picked_color.base = color_set_gb(context_raw.picked_color.base, buffer_get_u8(a, i1));
  228. context_raw.picked_color.base = color_set_bb(context_raw.picked_color.base, buffer_get_u8(a, i2));
  229. ui_header_handle.redraws = 2;
  230. if (context_raw.color_picker_callback != null) {
  231. context_raw.color_picker_callback(context_raw.picked_color);
  232. }
  233. });
  234. }
  235. }
  236. // UV map
  237. if (ui_view2d_type == view_2d_type_t.LAYER && ui_view2d_uvmap_show) {
  238. draw_scaled_image(util_uv_uvmap, tx, ty, tw, th);
  239. }
  240. // Menu
  241. let ew: i32 = math_floor(UI_ELEMENT_W());
  242. draw_set_color(ui.ops.theme.WINDOW_BG_COL);
  243. draw_filled_rect(0, UI_ELEMENT_H(), ui_view2d_ww, UI_ELEMENT_H() + UI_ELEMENT_OFFSET() * 2);
  244. draw_set_color(0xffffffff);
  245. let start_y: f32 = UI_ELEMENT_H() + UI_ELEMENT_OFFSET();
  246. ui._x = 2;
  247. ui._y = 2 + start_y;
  248. ui._w = ew;
  249. // Editable layer name
  250. let h: ui_handle_t = ui_handle(__ID__);
  251. let text: string = ui_view2d_type == view_2d_type_t.NODE ? context_raw.node_preview_name : h.text;
  252. ui._w = math_floor(math_min(draw_string_width(ui.ops.font, ui.font_size, text) + 15 * UI_SCALE(), 100 * UI_SCALE()));
  253. if (ui_view2d_type == view_2d_type_t.ASSET) {
  254. let asset: asset_t = context_raw.texture;
  255. if (asset != null) {
  256. let asset_names: string[] = project_asset_names;
  257. let i: i32 = array_index_of(asset_names, asset.name);
  258. h.text = asset.name;
  259. asset.name = ui_text_input(h, "");
  260. asset_names[i] = asset.name;
  261. }
  262. }
  263. else if (ui_view2d_type == view_2d_type_t.NODE) {
  264. ui_text(context_raw.node_preview_name);
  265. }
  266. else if (ui_view2d_type == view_2d_type_t.LAYER) {
  267. h.text = l.name;
  268. l.name = ui_text_input(h, "");
  269. ui_view2d_text_input_hover = ui.is_hovered;
  270. }
  271. else if (ui_view2d_type == view_2d_type_t.FONT) {
  272. h.text = context_raw.font.name;
  273. context_raw.font.name = ui_text_input(h, "");
  274. }
  275. if (h.changed) {
  276. ui_base_hwnds[0].redraws = 2;
  277. }
  278. ui._x += ui._w + 3;
  279. ui._y = 2 + start_y;
  280. ui._w = ew;
  281. if (ui_view2d_type == view_2d_type_t.LAYER) {
  282. let h_layer_mode: ui_handle_t = ui_handle(__ID__);
  283. if (h_layer_mode.init) {
  284. h_layer_mode.i = ui_view2d_layer_mode;
  285. }
  286. let layer_mode_combo: string[] = [ tr("Visible"), tr("Selected") ];
  287. ui_view2d_layer_mode = ui_combo(h_layer_mode, layer_mode_combo, tr("Layers"));
  288. ui._x += ew + 3;
  289. ui._y = 2 + start_y;
  290. if (!slot_layer_is_mask(context_raw.layer)) {
  291. let h_tex_type: ui_handle_t = ui_handle(__ID__);
  292. if (h_tex_type.init) {
  293. h_tex_type.i = ui_view2d_tex_type;
  294. }
  295. let tex_type_combo: string[] = [
  296. tr("Base Color"),
  297. tr("Normal Map"),
  298. tr("Occlusion"),
  299. tr("Roughness"),
  300. tr("Metallic"),
  301. tr("Opacity"),
  302. tr("Height"),
  303. ];
  304. ui_view2d_tex_type = ui_combo(h_tex_type, tex_type_combo, tr("Texture"));
  305. ui._x += ew + 3;
  306. ui._y = 2 + start_y;
  307. }
  308. ui._w = math_floor(ew * 0.7 + 3);
  309. let h_uvmap_show: ui_handle_t = ui_handle(__ID__);
  310. if (h_uvmap_show.init) {
  311. h_uvmap_show.b = ui_view2d_uvmap_show;
  312. }
  313. ui_view2d_uvmap_show = ui_check(h_uvmap_show, tr("UV Map"));
  314. ui._x += ew * 0.7 + 3;
  315. ui._y = 2 + start_y;
  316. }
  317. ui._w = math_floor(ew * 0.7 + 3);
  318. let h_tiled_show: ui_handle_t = ui_handle(__ID__);
  319. if (h_tiled_show.init) {
  320. h_tiled_show.b = ui_view2d_tiled_show;
  321. }
  322. ui_view2d_tiled_show = ui_check(h_tiled_show, tr("Tiled"));
  323. ui._x += ew * 0.6 + 3;
  324. ui._y = 2 + start_y;
  325. if (tex != null) {
  326. ui._w = math_floor(ew * 0.5 + 3);
  327. let scale_percent: i32 = math_round((tw / tex.width) * 100);
  328. if (ui_text(scale_percent + "%") == ui_state_t.STARTED) {
  329. ui_view2d_pan_scale = tex.width / (ui_view2d_ww * 0.95);
  330. }
  331. ui._x += ew * 0.5 + 3;
  332. ui._y = 2 + start_y;
  333. }
  334. ui.enabled = false;
  335. if ((ui_view2d_type == view_2d_type_t.ASSET || ui_view2d_type == view_2d_type_t.NODE) && tex != null) { // Texture resolution
  336. ui._w = math_floor(ew * 0.7 + 3);
  337. ui_text(tex.width + "x" + tex.height);
  338. ui._x += ew * 0.7 + 3;
  339. ui._y = 2 + start_y;
  340. }
  341. let view_type: string = ui_view2d_type == view_2d_type_t.ASSET ? "Asset"
  342. : ui_view2d_type == view_2d_type_t.NODE ? "Node"
  343. : ui_view2d_type == view_2d_type_t.FONT ? "Font"
  344. : "Layer";
  345. ui._w = math_floor(ew * 0.5 + 3);
  346. ui_text(view_type);
  347. ui._x += ew * 0.5 + 3;
  348. ui._y = 2 + start_y;
  349. ui.enabled = true;
  350. // Picked position
  351. if (context_raw.tool == tool_type_t.PICKER && (ui_view2d_type == view_2d_type_t.LAYER || ui_view2d_type == view_2d_type_t.ASSET)) {
  352. let cursor_img: gpu_texture_t = resource_get("cursor.k");
  353. let hsize: f32 = 16 * UI_SCALE();
  354. let size: f32 = hsize * 2;
  355. draw_scaled_image(cursor_img, tx + tw * context_raw.uvx_picked - hsize, ty + th * context_raw.uvy_picked - hsize, size, size);
  356. }
  357. }
  358. ui_end();
  359. }
  360. function ui_view2d_update() {
  361. let headerh: f32 = UI_ELEMENT_H() * 1.4;
  362. context_raw.paint2d = false;
  363. if (!base_ui_enabled || !ui_view2d_show || mouse_x < ui_view2d_wx || mouse_x > ui_view2d_wx + ui_view2d_ww || mouse_y < ui_view2d_wy + headerh ||
  364. mouse_y > ui_view2d_wy + ui_view2d_wh) {
  365. if (ui_view2d_controls_down) {
  366. let control: ui_canvas_control_t = ui_nodes_get_canvas_control(ui_view2d_controls_down);
  367. ui_view2d_controls_down = control.controls_down;
  368. }
  369. return;
  370. }
  371. let control: ui_canvas_control_t = ui_nodes_get_canvas_control(ui_view2d_controls_down);
  372. ui_view2d_pan_x += control.pan_x;
  373. ui_view2d_pan_y += control.pan_y;
  374. ui_view2d_controls_down = control.controls_down;
  375. if (control.zoom != 0.0) {
  376. let _pan_x: f32 = ui_view2d_pan_x / ui_view2d_pan_scale;
  377. let _pan_y: f32 = ui_view2d_pan_y / ui_view2d_pan_scale;
  378. ui_view2d_pan_scale += control.zoom;
  379. if (ui_view2d_pan_scale < 0.1) {
  380. ui_view2d_pan_scale = 0.1;
  381. }
  382. if (ui_view2d_pan_scale > 6.0) {
  383. ui_view2d_pan_scale = 6.0;
  384. }
  385. ui_view2d_pan_x = _pan_x * ui_view2d_pan_scale;
  386. ui_view2d_pan_y = _pan_y * ui_view2d_pan_scale;
  387. if (ui_touch_scroll) {
  388. // Zoom to finger location
  389. ui_view2d_pan_x -= (ui.input_x - ui._window_x - ui._window_w / 2) * control.zoom;
  390. ui_view2d_pan_y -= (ui.input_y - ui._window_y - ui._window_h / 2) * control.zoom;
  391. }
  392. ui_view2d_grid_redraw = true;
  393. }
  394. let decal_mask: bool = context_is_decal_mask_paint();
  395. let set_clone_source: bool =
  396. context_raw.tool == tool_type_t.CLONE &&
  397. operator_shortcut(map_get(config_keymap, "set_clone_source") + "+" + map_get(config_keymap, "action_paint"), shortcut_type_t.DOWN);
  398. let bake: bool = context_raw.tool == tool_type_t.BAKE;
  399. if (ui_view2d_type == view_2d_type_t.LAYER && !ui_view2d_text_input_hover && !bake &&
  400. (operator_shortcut(map_get(config_keymap, "action_paint"), shortcut_type_t.DOWN) ||
  401. operator_shortcut(map_get(config_keymap, "brush_ruler") + "+" + map_get(config_keymap, "action_paint"), shortcut_type_t.DOWN) || decal_mask ||
  402. set_clone_source || config_raw.brush_live)) {
  403. // Same mapping for paint and rotate (predefined in touch keymap)
  404. let paint_key: string = map_get(config_keymap, "action_paint");
  405. let rotate_key: string = map_get(config_keymap, "action_rotate");
  406. if (paint_key == rotate_key) {
  407. // Paint only when clicking on the layer rect
  408. let layer: slot_layer_t = context_raw.layer;
  409. let tex: gpu_texture_t = layer.texpaint;
  410. let ratio: f32 = tex.height / tex.width;
  411. let tw: f32 = ui_view2d_ww * 0.95 * ui_view2d_pan_scale;
  412. let th: f32 = tw * ratio;
  413. let tx: f32 = ui_view2d_ww / 2 - tw / 2 + ui_view2d_pan_x;
  414. let headerh: i32 = config_raw.layout[layout_size_t.HEADER] == 1 ? ui_header_h * 2 : ui_header_h;
  415. let apph: i32 = iron_window_height() - config_raw.layout[layout_size_t.STATUS_H] + headerh;
  416. let ty: f32 = apph / 2 - th / 2 + ui_view2d_pan_y;
  417. let mx: f32 = mouse_x - ui_view2d_wx;
  418. let my: f32 = mouse_y - ui_view2d_wy;
  419. if (mx > tx && mx < tx + tw && my > ty && my < ty + th) {
  420. context_raw.paint2d = true;
  421. }
  422. }
  423. else {
  424. context_raw.paint2d = true;
  425. }
  426. }
  427. if (ui.is_typing) {
  428. return;
  429. }
  430. if (keyboard_started("left")) {
  431. ui_view2d_pan_x -= 5;
  432. }
  433. else if (keyboard_started("right")) {
  434. ui_view2d_pan_x += 5;
  435. }
  436. if (keyboard_started("up")) {
  437. ui_view2d_pan_y -= 5;
  438. }
  439. else if (keyboard_started("down")) {
  440. ui_view2d_pan_y += 5;
  441. }
  442. // Limit panning to keep texture in viewport
  443. let border: i32 = 32;
  444. let tw: f32 = ui_view2d_ww * 0.95 * ui_view2d_pan_scale;
  445. let tx: f32 = ui_view2d_ww / 2 - tw / 2 + ui_view2d_pan_x;
  446. let hh: f32 = sys_h();
  447. let ty: f32 = hh / 2 - tw / 2 + ui_view2d_pan_y;
  448. if (tx + border > ui_view2d_ww) {
  449. ui_view2d_pan_x = ui_view2d_ww / 2 + tw / 2 - border;
  450. }
  451. else if (tx - border < -tw) {
  452. ui_view2d_pan_x = -tw / 2 - ui_view2d_ww / 2 + border;
  453. }
  454. if (ty + border > hh) {
  455. ui_view2d_pan_y = hh / 2 + tw / 2 - border;
  456. }
  457. else if (ty - border < -tw) {
  458. ui_view2d_pan_y = -tw / 2 - hh / 2 + border;
  459. }
  460. if (operator_shortcut(map_get(config_keymap, "view_reset"))) {
  461. ui_view2d_pan_x = 0.0;
  462. ui_view2d_pan_y = 0.0;
  463. ui_view2d_pan_scale = 1.0;
  464. }
  465. }