gfx.rs 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  1. use darkfi_serial::{Decodable, Encodable, SerialDecodable, SerialEncodable};
  2. use freetype as ft;
  3. use miniquad::{
  4. conf, window, Backend, Bindings, BlendFactor, BlendState, BlendValue, BufferId, BufferLayout,
  5. BufferSource, BufferType, BufferUsage, Equation, EventHandler, KeyCode, KeyMods, MouseButton,
  6. PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource, TextureId,
  7. UniformDesc, UniformType, VertexAttribute, VertexFormat,
  8. };
  9. use std::{
  10. array::IntoIter,
  11. fmt,
  12. io::Cursor,
  13. sync::{mpsc, Arc, MutexGuard},
  14. time::{Duration, Instant},
  15. };
  16. use crate::{
  17. error::{Error, Result},
  18. chatview,
  19. editbox,
  20. expr::{SExprMachine, SExprVal},
  21. keysym::{KeyCodeAsStr, MouseButtonAsU8},
  22. prop::{Property, PropertySubType, PropertyType},
  23. res::{ResourceId, ResourceManager},
  24. scene::{
  25. MethodResponseFn, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
  26. SceneNodeType, Pimpl
  27. },
  28. shader,
  29. };
  30. type Color = [f32; 4];
  31. pub const COLOR_RED: Color = [1., 0., 0., 1.];
  32. pub const COLOR_DARKGREY: Color = [0.2, 0.2, 0.2, 1.];
  33. pub const COLOR_GREEN: Color = [0., 1., 0., 1.];
  34. pub const COLOR_BLUE: Color = [0., 0., 1., 1.];
  35. pub const COLOR_WHITE: Color = [1., 1., 1., 1.];
  36. #[derive(Debug, SerialEncodable, SerialDecodable)]
  37. #[repr(C)]
  38. struct Vertex {
  39. pos: [f32; 2],
  40. color: [f32; 4],
  41. uv: [f32; 2],
  42. }
  43. #[derive(SerialEncodable, SerialDecodable)]
  44. #[repr(C)]
  45. struct Face {
  46. idxs: [u32; 3],
  47. }
  48. impl fmt::Debug for Face {
  49. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  50. write!(f, "{:?}", self.idxs)
  51. }
  52. }
  53. struct Mesh {
  54. pub verts: Vec<Vertex>,
  55. pub faces: Vec<Face>,
  56. pub vertex_buffer: BufferId,
  57. pub index_buffer: BufferId,
  58. }
  59. pub struct Point<T> {
  60. pub x: T,
  61. pub y: T,
  62. }
  63. #[derive(Debug, Clone)]
  64. pub struct Rectangle<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::cmp::PartialOrd> {
  65. pub x: T,
  66. pub y: T,
  67. pub w: T,
  68. pub h: T,
  69. }
  70. impl<T: Copy + std::ops::Add<Output=T> + std::ops::Sub<Output=T> + std::ops::AddAssign + std::cmp::PartialOrd> Rectangle<T> {
  71. fn from_array(arr: [T; 4]) -> Self {
  72. let mut iter = IntoIter::new(arr);
  73. Self {
  74. x: iter.next().unwrap(),
  75. y: iter.next().unwrap(),
  76. w: iter.next().unwrap(),
  77. h: iter.next().unwrap(),
  78. }
  79. }
  80. pub fn clip(&self, other: &Self) -> Option<Self> {
  81. if other.x + other.w < self.x ||
  82. other.x > self.x + self.w ||
  83. other.y + other.h < self.y ||
  84. other.y > self.y + self.h
  85. {
  86. return None
  87. }
  88. let mut clipped = other.clone();
  89. if clipped.x < self.x {
  90. clipped.x = self.x;
  91. clipped.w = other.x + other.w - clipped.x;
  92. }
  93. if clipped.y < self.y {
  94. clipped.y = self.y;
  95. clipped.h = other.y + other.h - clipped.y;
  96. }
  97. if clipped.x + clipped.w > self.x + self.w {
  98. clipped.w = self.x + self.w - clipped.x;
  99. }
  100. if clipped.y + clipped.h > self.y + self.h {
  101. clipped.h = self.y + self.h - clipped.y;
  102. }
  103. Some(clipped)
  104. }
  105. pub fn contains(&self, point: &Point<T>) -> bool {
  106. self.x < point.x && point.x < self.x + self.w &&
  107. self.y < point.y && point.y < self.y + self.h
  108. }
  109. }
  110. pub type FreetypeFace = ft::Face<&'static [u8]>;
  111. #[derive(Debug)]
  112. enum GraphicsMethodEvent {
  113. LoadTexture,
  114. DeleteTexture,
  115. CreateChatView,
  116. CreateEditBox,
  117. }
  118. struct Stage {
  119. ctx: Box<dyn RenderingBackend>,
  120. pipeline: Pipeline,
  121. scene_graph: SceneGraphPtr,
  122. textures: ResourceManager<TextureId>,
  123. font_faces: Vec<FreetypeFace>,
  124. method_recvr: mpsc::Receiver<(GraphicsMethodEvent, SceneNodeId, Vec<u8>, MethodResponseFn)>,
  125. method_sender: mpsc::SyncSender<(GraphicsMethodEvent, SceneNodeId, Vec<u8>, MethodResponseFn)>,
  126. last_draw_time: Option<Instant>,
  127. }
  128. impl Stage {
  129. const WHITE_TEXTURE_ID: ResourceId = 0;
  130. pub fn new(scene_graph: SceneGraphPtr) -> Self {
  131. let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
  132. let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
  133. let mut textures = ResourceManager::new();
  134. let white_texture_id = textures.alloc(white_texture);
  135. assert_eq!(white_texture_id, Self::WHITE_TEXTURE_ID);
  136. let mut shader_meta: ShaderMeta = shader::meta();
  137. shader_meta.uniforms.uniforms.push(UniformDesc::new("Projection", UniformType::Mat4));
  138. shader_meta.uniforms.uniforms.push(UniformDesc::new("Model", UniformType::Mat4));
  139. let shader = ctx
  140. .new_shader(
  141. match ctx.info().backend {
  142. Backend::OpenGl => ShaderSource::Glsl {
  143. vertex: shader::GL_VERTEX,
  144. fragment: shader::GL_FRAGMENT,
  145. },
  146. Backend::Metal => ShaderSource::Msl { program: shader::METAL },
  147. },
  148. shader_meta,
  149. )
  150. .unwrap();
  151. let params = PipelineParams {
  152. color_blend: Some(BlendState::new(
  153. Equation::Add,
  154. BlendFactor::Value(BlendValue::SourceAlpha),
  155. BlendFactor::OneMinusValue(BlendValue::SourceAlpha),
  156. )),
  157. ..Default::default()
  158. };
  159. let pipeline = ctx.new_pipeline(
  160. &[BufferLayout::default()],
  161. &[
  162. VertexAttribute::new("in_pos", VertexFormat::Float2),
  163. VertexAttribute::new("in_color", VertexFormat::Float4),
  164. VertexAttribute::new("in_uv", VertexFormat::Float2),
  165. ],
  166. shader,
  167. params,
  168. );
  169. let (method_sender, method_recvr) = mpsc::sync_channel(100);
  170. let ftlib = ft::Library::init().unwrap();
  171. let mut font_faces = vec![];
  172. let font_data = include_bytes!("../ibm-plex-mono-light.otf") as &[u8];
  173. let ft_face = ftlib.new_memory_face2(font_data, 0).unwrap();
  174. font_faces.push(ft_face);
  175. let font_data = include_bytes!("../NotoColorEmoji.ttf") as &[u8];
  176. let ft_face = ftlib.new_memory_face2(font_data, 0).unwrap();
  177. font_faces.push(ft_face);
  178. let mut stage = Stage {
  179. ctx,
  180. pipeline,
  181. scene_graph,
  182. textures,
  183. font_faces,
  184. method_recvr,
  185. method_sender,
  186. last_draw_time: None,
  187. };
  188. stage.setup_scene_graph_window();
  189. debug!("Finished loading GUI");
  190. stage
  191. }
  192. fn setup_scene_graph_window(&mut self) {
  193. let mut scene_graph = self.scene_graph.lock().unwrap();
  194. let window = scene_graph.add_node("window", SceneNodeType::Window);
  195. let (screen_width, screen_height) = window::screen_size();
  196. let mut prop = Property::new("screen_size", PropertyType::Float32, PropertySubType::Pixel);
  197. prop.set_array_len(2);
  198. prop.set_f32(0, screen_width);
  199. prop.set_f32(1, screen_height);
  200. window.add_property(prop).unwrap();
  201. window
  202. .add_signal(
  203. "resize",
  204. "Screen resize event",
  205. vec![
  206. ("screen_width", "", PropertyType::Float32),
  207. ("screen_height", "", PropertyType::Float32),
  208. ],
  209. )
  210. .unwrap();
  211. let window_id = window.id;
  212. let sender = self.method_sender.clone();
  213. let method_fn = Box::new(move |arg_data, response_fn| {
  214. sender.send((GraphicsMethodEvent::LoadTexture, window_id, arg_data, response_fn));
  215. });
  216. window
  217. .add_method(
  218. "load_texture",
  219. vec![("node_name", "", PropertyType::Str), ("path", "", PropertyType::Str)],
  220. vec![("node_id", "", PropertyType::SceneNodeId)],
  221. method_fn,
  222. )
  223. .unwrap();
  224. let sender = self.method_sender.clone();
  225. let method_fn = Box::new(move |arg_data, response_fn| {
  226. sender.send((GraphicsMethodEvent::CreateChatView, window_id, arg_data, response_fn));
  227. });
  228. window
  229. .add_method(
  230. "create_chat_view",
  231. vec![("node_id", "", PropertyType::SceneNodeId)],
  232. vec![],
  233. method_fn,
  234. )
  235. .unwrap();
  236. let sender = self.method_sender.clone();
  237. let method_fn = Box::new(move |arg_data, response_fn| {
  238. sender.send((GraphicsMethodEvent::CreateEditBox, window_id, arg_data, response_fn));
  239. });
  240. window
  241. .add_method(
  242. "create_edit_box",
  243. vec![("node_id", "", PropertyType::SceneNodeId)],
  244. vec![],
  245. method_fn,
  246. )
  247. .unwrap();
  248. scene_graph.link(window_id, SceneGraph::ROOT_ID).unwrap();
  249. let input = scene_graph.add_node("input", SceneNodeType::WindowInput);
  250. let input_id = input.id;
  251. scene_graph.link(input_id, window_id).unwrap();
  252. let keyb = scene_graph.add_node("keyboard", SceneNodeType::Keyboard);
  253. keyb.add_signal(
  254. "key_down",
  255. "Key press down event",
  256. vec![
  257. ("shift", "", PropertyType::Bool),
  258. ("ctrl", "", PropertyType::Bool),
  259. ("alt", "", PropertyType::Bool),
  260. ("logo", "", PropertyType::Bool),
  261. ("repeat", "", PropertyType::Bool),
  262. ("keycode", "", PropertyType::Enum),
  263. ],
  264. )
  265. .unwrap();
  266. keyb.add_signal(
  267. "key_up",
  268. "Key press up event",
  269. vec![
  270. ("shift", "", PropertyType::Bool),
  271. ("ctrl", "", PropertyType::Bool),
  272. ("alt", "", PropertyType::Bool),
  273. ("logo", "", PropertyType::Bool),
  274. ("repeat", "", PropertyType::Bool),
  275. ("keycode", "", PropertyType::Enum),
  276. ],
  277. )
  278. .unwrap();
  279. let keyb_id = keyb.id;
  280. scene_graph.link(keyb_id, input_id).unwrap();
  281. let mouse = scene_graph.add_node("mouse", SceneNodeType::Mouse);
  282. mouse
  283. .add_signal(
  284. "button_up",
  285. "Mouse button up event",
  286. vec![
  287. ("button", "", PropertyType::Enum),
  288. ("x", "", PropertyType::Float32),
  289. ("y", "", PropertyType::Float32),
  290. ],
  291. )
  292. .unwrap();
  293. mouse
  294. .add_signal(
  295. "button_down",
  296. "Mouse button down event",
  297. vec![
  298. ("button", "", PropertyType::Enum),
  299. ("x", "", PropertyType::Float32),
  300. ("y", "", PropertyType::Float32),
  301. ],
  302. )
  303. .unwrap();
  304. mouse
  305. .add_signal(
  306. "wheel",
  307. "Mouse wheel scroll event",
  308. vec![("x", "", PropertyType::Float32), ("y", "", PropertyType::Float32)],
  309. )
  310. .unwrap();
  311. mouse
  312. .add_signal(
  313. "move",
  314. "Mouse cursor move event",
  315. vec![("x", "", PropertyType::Float32), ("y", "", PropertyType::Float32)],
  316. )
  317. .unwrap();
  318. let mouse_id = mouse.id;
  319. scene_graph.link(mouse_id, input_id).unwrap();
  320. }
  321. fn method_load_texture(&mut self, node_id: SceneNodeId, arg_data: Vec<u8>) -> Result<Vec<u8>> {
  322. let mut cur = Cursor::new(&arg_data);
  323. let node_name = String::decode(&mut cur).unwrap();
  324. let filepath = String::decode(&mut cur).unwrap();
  325. let Ok(img) = image::open(filepath) else { return Err(Error::FileNotFound) };
  326. let img = img.to_rgba8();
  327. let width = img.width();
  328. let height = img.height();
  329. let bmp = img.into_raw();
  330. let texture = self.ctx.new_texture_from_rgba8(width as u16, height as u16, &bmp);
  331. let id = self.textures.alloc(texture);
  332. let mut scene_graph = self.scene_graph.lock().unwrap();
  333. let img_node = scene_graph.add_node(node_name, SceneNodeType::RenderTexture);
  334. let mut prop = Property::new("size", PropertyType::Uint32, PropertySubType::Pixel);
  335. prop.set_array_len(2);
  336. prop.set_u32(0, width).unwrap();
  337. prop.set_u32(1, height).unwrap();
  338. img_node.add_property(prop)?;
  339. let mut prop =
  340. Property::new("texture_rid", PropertyType::Uint32, PropertySubType::ResourceId);
  341. prop.set_u32(0, id).unwrap();
  342. img_node.add_property(prop)?;
  343. let mut reply = vec![];
  344. img_node.id.encode(&mut reply).unwrap();
  345. Ok(reply)
  346. }
  347. fn method_delete_texture(
  348. &mut self,
  349. node_id: SceneNodeId,
  350. arg_data: Vec<u8>,
  351. ) -> Result<Vec<u8>> {
  352. let mut cur = Cursor::new(&arg_data);
  353. let texture_id = ResourceId::decode(&mut cur).unwrap();
  354. let texture = self.textures.get(texture_id).ok_or(Error::ResourceNotFound)?;
  355. self.ctx.delete_texture(*texture);
  356. self.textures.free(texture_id);
  357. Ok(vec![])
  358. }
  359. fn method_create_chatview(
  360. &mut self,
  361. _: SceneNodeId,
  362. arg_data: Vec<u8>,
  363. ) -> Result<Vec<u8>> {
  364. let mut cur = Cursor::new(&arg_data);
  365. let node_id = SceneNodeId::decode(&mut cur).unwrap();
  366. let mut scene_graph = self.scene_graph.lock().unwrap();
  367. let editbox = chatview::ChatView::new(&mut scene_graph, node_id, self.font_faces.clone())?;
  368. let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
  369. node.pimpl = editbox;
  370. let mut reply = vec![];
  371. Ok(reply)
  372. }
  373. fn method_create_editbox(
  374. &mut self,
  375. _: SceneNodeId,
  376. arg_data: Vec<u8>,
  377. ) -> Result<Vec<u8>> {
  378. let mut cur = Cursor::new(&arg_data);
  379. let node_id = SceneNodeId::decode(&mut cur).unwrap();
  380. let mut scene_graph = self.scene_graph.lock().unwrap();
  381. let editbox = editbox::EditBox::new(&mut scene_graph, node_id, self.font_faces.clone())?;
  382. let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
  383. node.pimpl = editbox;
  384. let mut reply = vec![];
  385. Ok(reply)
  386. }
  387. }
  388. pub struct RenderContext<'a> {
  389. pub scene_graph: MutexGuard<'a, SceneGraph>,
  390. pub ctx: &'a mut Box<dyn RenderingBackend>,
  391. pub pipeline: &'a Pipeline,
  392. pub proj: glam::Mat4,
  393. pub textures: &'a ResourceManager<TextureId>,
  394. pub font_faces: &'a Vec<FreetypeFace>,
  395. }
  396. impl<'a> RenderContext<'a> {
  397. fn render_window(&mut self) {
  398. for layer in self
  399. .scene_graph
  400. .lookup_node("/window")
  401. .expect("no window attached!")
  402. .get_children(&[SceneNodeType::RenderLayer])
  403. {
  404. if let Err(err) = self.render_layer(layer.id) {
  405. error!("error rendering layer '{}': {}", layer.name, err)
  406. }
  407. }
  408. self.ctx.commit_frame();
  409. }
  410. fn get_rect(layer: &SceneNode) -> Result<Rectangle<i32>> {
  411. let prop = layer.get_property("rect").ok_or(Error::PropertyNotFound)?;
  412. if prop.array_len != 4 {
  413. return Err(Error::PropertyWrongLen)
  414. }
  415. let mut rect = [0; 4];
  416. for i in 0..4 {
  417. if prop.is_expr(i)? {
  418. let (screen_width, screen_height) = window::screen_size();
  419. let expr = prop.get_expr(i).unwrap();
  420. let machine = SExprMachine {
  421. globals: vec![
  422. ("sw".to_string(), SExprVal::Float32(screen_width)),
  423. ("sh".to_string(), SExprVal::Float32(screen_height)),
  424. ],
  425. stmts: &expr,
  426. };
  427. rect[i] = machine.call()?.as_u32()? as i32;
  428. } else {
  429. rect[i] = prop.get_u32(i)? as i32;
  430. }
  431. }
  432. Ok(Rectangle::from_array(rect))
  433. }
  434. fn render_layer(
  435. &mut self,
  436. layer_id: SceneNodeId,
  437. // parent rect
  438. ) -> Result<()> {
  439. let layer = self.scene_graph.get_node(layer_id).unwrap();
  440. if !layer.get_property_bool("is_visible")? {
  441. return Ok(())
  442. }
  443. self.ctx.begin_default_pass(PassAction::Nothing);
  444. self.ctx.apply_pipeline(&self.pipeline);
  445. let (_, screen_height) = window::screen_size();
  446. let rect = Self::get_rect(&layer)?;
  447. let mut view = rect.clone();
  448. view.y = screen_height as i32 - (rect.y + rect.h);
  449. self.ctx.apply_viewport(view.x, view.y, view.w, view.h);
  450. self.ctx.apply_scissor_rect(view.x, view.y, view.w, view.h);
  451. let rect = Rectangle {
  452. x: rect.x as f32,
  453. y: rect.y as f32,
  454. w: rect.w as f32,
  455. h: rect.h as f32,
  456. };
  457. let layer_children =
  458. layer.get_children(&[SceneNodeType::RenderMesh, SceneNodeType::RenderText, SceneNodeType::EditBox, SceneNodeType::ChatView]);
  459. let layer_children = self.order_by_z_index(layer_children);
  460. // get the rectangle
  461. // make sure it's inside the parent's rect
  462. for child in layer_children {
  463. // x, y, w, h as pixels
  464. // note that (x, y) is offset by layer rect so it is the pos within layer
  465. // layer coords are (0, 0) -> (1, 1)
  466. // optionally evaluated using sexpr
  467. // mesh data is (0, 0) to (1, 1)
  468. // so scale by (w, h)
  469. match child.typ {
  470. SceneNodeType::RenderMesh => {
  471. if let Err(err) = self.render_mesh(child.id, &rect) {
  472. error!("error rendering mesh '{}': {}", child.name, err);
  473. }
  474. }
  475. SceneNodeType::RenderText => {
  476. if let Err(err) = self.render_text(child.id, &rect) {
  477. error!("error rendering text '{}': {}", child.name, err);
  478. }
  479. }
  480. SceneNodeType::ChatView => {
  481. let node = self.scene_graph.get_node(child.id).unwrap();
  482. let chatview = match &node.pimpl {
  483. Pimpl::ChatView(e) => e.clone(),
  484. _ => panic!("wrong pimpl for editbox")
  485. };
  486. if let Err(err) = chatview.render(self, child.id, &rect) {
  487. error!("error rendering chatview '{}': {}", child.name, err);
  488. }
  489. }
  490. SceneNodeType::EditBox => {
  491. let node = self.scene_graph.get_node(child.id).unwrap();
  492. let editbox = match &node.pimpl {
  493. Pimpl::EditBox(e) => e.clone(),
  494. _ => panic!("wrong pimpl for editbox")
  495. };
  496. if let Err(err) = editbox.render(self, child.id, &rect) {
  497. error!("error rendering editbox '{}': {}", child.name, err);
  498. }
  499. }
  500. _ => panic!("render_layer(): unknown type"),
  501. }
  502. }
  503. Ok(())
  504. }
  505. fn order_by_z_index(&self, nodes: Vec<SceneNodeInfo>) -> Vec<SceneNodeInfo> {
  506. let mut nodes: Vec<_> = nodes
  507. .into_iter()
  508. .filter_map(|node_inf| {
  509. let node = self.scene_graph.get_node(node_inf.id).unwrap();
  510. //if !node.get_property_bool("is_visible").ok()? {
  511. // return None
  512. //}
  513. let z_index = node.get_property_u32("z_index").ok()?;
  514. Some((z_index, node_inf))
  515. })
  516. .collect();
  517. nodes.sort_unstable_by_key(|(z_index, node_inf)| *z_index);
  518. nodes.into_iter().map(|(z_index, node_inf)| node_inf).collect()
  519. }
  520. pub fn get_dim(mesh: &SceneNode, layer_rect: &Rectangle<f32>) -> Result<Rectangle<f32>> {
  521. let prop = mesh.get_property("rect").ok_or(Error::PropertyNotFound)?;
  522. if prop.array_len != 4 {
  523. return Err(Error::PropertyWrongLen)
  524. }
  525. let mut rect = [0.; 4];
  526. for i in 0..4 {
  527. if prop.is_expr(i)? {
  528. let expr = prop.get_expr(i).unwrap();
  529. let machine = SExprMachine {
  530. globals: vec![
  531. ("lw".to_string(), SExprVal::Uint32(layer_rect.w as u32)),
  532. ("lh".to_string(), SExprVal::Uint32(layer_rect.h as u32)),
  533. ],
  534. stmts: &expr,
  535. };
  536. rect[i] = machine.call()?.coerce_f32()?;
  537. } else {
  538. rect[i] = prop.get_f32(i)?;
  539. }
  540. }
  541. Ok(Rectangle::from_array(rect))
  542. }
  543. fn render_mesh(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
  544. let mesh = self.scene_graph.get_node(node_id).unwrap();
  545. let z_index = mesh.get_property_u32("z_index")?;
  546. let data = mesh.get_property("data").ok_or(Error::PropertyNotFound)?;
  547. let verts = data.get_buf(0)?;
  548. let faces = data.get_buf(1)?;
  549. let vertex_buffer = self.ctx.new_buffer(
  550. BufferType::VertexBuffer,
  551. BufferUsage::Immutable,
  552. BufferSource::slice(&verts),
  553. );
  554. let bufsrc = unsafe {
  555. BufferSource::pointer(
  556. faces.as_ptr() as _,
  557. std::mem::size_of_val(&faces[..]),
  558. std::mem::size_of::<u32>(),
  559. )
  560. };
  561. let index_buffer =
  562. self.ctx.new_buffer(BufferType::IndexBuffer, BufferUsage::Immutable, bufsrc);
  563. // temp
  564. let texture = self.textures.get(Stage::WHITE_TEXTURE_ID).unwrap();
  565. let rect = Self::get_dim(mesh, layer_rect)?;
  566. //debug!("mesh rect: {:?}", rect);
  567. let layer_w = layer_rect.w as f32;
  568. let layer_h = layer_rect.h as f32;
  569. let off_x = rect.x / layer_w;
  570. let off_y = rect.y / layer_h;
  571. let scale_x = rect.w / layer_w;
  572. let scale_y = rect.h / layer_h;
  573. //let model = glam::Mat4::IDENTITY;
  574. let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
  575. glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
  576. let mut uniforms_data = [0u8; 128];
  577. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&self.proj) };
  578. uniforms_data[0..64].copy_from_slice(&data);
  579. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
  580. uniforms_data[64..].copy_from_slice(&data);
  581. assert_eq!(128, 2 * UniformType::Mat4.size());
  582. let bindings =
  583. Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![*texture] };
  584. self.ctx.apply_bindings(&bindings);
  585. self.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
  586. self.ctx.draw(0, 3 * faces.len() as i32, 1);
  587. self.ctx.delete_buffer(index_buffer);
  588. self.ctx.delete_buffer(vertex_buffer);
  589. Ok(())
  590. }
  591. pub fn render_clipped_box_with_texture2(
  592. &mut self,
  593. bound: &Rectangle<f32>,
  594. obj: &Rectangle<f32>,
  595. color: Color,
  596. texture: TextureId,
  597. ) {
  598. let Some(clipped) = bound.clip(&obj) else {
  599. return
  600. };
  601. let x1 = clipped.x;
  602. let y1 = clipped.y;
  603. let x2 = clipped.x + clipped.w;
  604. let y2 = clipped.y + clipped.h;
  605. let u1 = (clipped.x - obj.x) / obj.w;
  606. let u2 = (clipped.x + clipped.w - obj.x) / obj.w;
  607. let v1 = (clipped.y - obj.y) / obj.h;
  608. let v2 = (clipped.y + clipped.h - obj.y) / obj.h;
  609. let vertices: [Vertex; 4] = [
  610. // top left
  611. Vertex { pos: [x1, y1], color, uv: [u1, v1] },
  612. // top right
  613. Vertex { pos: [x2, y1], color, uv: [u2, v1] },
  614. // bottom left
  615. Vertex { pos: [x1, y2], color, uv: [u1, v2] },
  616. // bottom right
  617. Vertex { pos: [x2, y2], color, uv: [u2, v2] },
  618. ];
  619. //debug!("screen size: {:?}", window::screen_size());
  620. let vertex_buffer = self.ctx.new_buffer(
  621. BufferType::VertexBuffer,
  622. BufferUsage::Immutable,
  623. BufferSource::slice(&vertices),
  624. );
  625. let indices: [u16; 6] = [0, 2, 1, 1, 2, 3];
  626. let index_buffer = self.ctx.new_buffer(
  627. BufferType::IndexBuffer,
  628. BufferUsage::Immutable,
  629. BufferSource::slice(&indices),
  630. );
  631. let bindings =
  632. Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![texture] };
  633. self.ctx.apply_bindings(&bindings);
  634. self.ctx.draw(0, 6, 1);
  635. }
  636. pub fn render_clipped_box_with_texture(
  637. &mut self,
  638. bound_rect: &Rectangle<f32>,
  639. x1: f32,
  640. y1: f32,
  641. x2: f32,
  642. y2: f32,
  643. color: Color,
  644. texture: TextureId,
  645. ) {
  646. let obj = Rectangle {
  647. x: x1,
  648. y: y1,
  649. w: x2 - x1,
  650. h: y2 - y1
  651. };
  652. if obj.w == 0. || obj.h == 0. {
  653. return
  654. }
  655. let Some(clipped) = bound_rect.clip(&obj) else {
  656. return
  657. };
  658. let x1 = clipped.x;
  659. let y1 = clipped.y;
  660. let x2 = clipped.x + clipped.w;
  661. let y2 = clipped.y + clipped.h;
  662. let u1 = (clipped.x - obj.x) / obj.w;
  663. let u2 = (clipped.x + clipped.w - obj.x) / obj.w;
  664. let v1 = (clipped.y - obj.y) / obj.h;
  665. let v2 = (clipped.y + clipped.h - obj.y) / obj.h;
  666. let vertices: [Vertex; 4] = [
  667. // top left
  668. Vertex { pos: [x1, y1], color, uv: [u1, v1] },
  669. // top right
  670. Vertex { pos: [x2, y1], color, uv: [u2, v1] },
  671. // bottom left
  672. Vertex { pos: [x1, y2], color, uv: [u1, v2] },
  673. // bottom right
  674. Vertex { pos: [x2, y2], color, uv: [u2, v2] },
  675. ];
  676. //debug!("screen size: {:?}", window::screen_size());
  677. let vertex_buffer = self.ctx.new_buffer(
  678. BufferType::VertexBuffer,
  679. BufferUsage::Immutable,
  680. BufferSource::slice(&vertices),
  681. );
  682. let indices: [u16; 6] = [0, 2, 1, 1, 2, 3];
  683. let index_buffer = self.ctx.new_buffer(
  684. BufferType::IndexBuffer,
  685. BufferUsage::Immutable,
  686. BufferSource::slice(&indices),
  687. );
  688. let bindings =
  689. Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![texture] };
  690. self.ctx.apply_bindings(&bindings);
  691. self.ctx.draw(0, 6, 1);
  692. }
  693. pub fn render_box_with_texture(
  694. &mut self,
  695. x1: f32,
  696. y1: f32,
  697. x2: f32,
  698. y2: f32,
  699. color: Color,
  700. texture: TextureId,
  701. ) {
  702. let vertices: [Vertex; 4] = [
  703. // top left
  704. Vertex { pos: [x1, y1], color, uv: [0., 0.] },
  705. // top right
  706. Vertex { pos: [x2, y1], color, uv: [1., 0.] },
  707. // bottom left
  708. Vertex { pos: [x1, y2], color, uv: [0., 1.] },
  709. // bottom right
  710. Vertex { pos: [x2, y2], color, uv: [1., 1.] },
  711. ];
  712. //debug!("screen size: {:?}", window::screen_size());
  713. let vertex_buffer = self.ctx.new_buffer(
  714. BufferType::VertexBuffer,
  715. BufferUsage::Immutable,
  716. BufferSource::slice(&vertices),
  717. );
  718. let indices: [u16; 6] = [0, 2, 1, 1, 2, 3];
  719. let index_buffer = self.ctx.new_buffer(
  720. BufferType::IndexBuffer,
  721. BufferUsage::Immutable,
  722. BufferSource::slice(&indices),
  723. );
  724. let bindings =
  725. Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![texture] };
  726. self.ctx.apply_bindings(&bindings);
  727. self.ctx.draw(0, 6, 1);
  728. }
  729. pub fn render_box(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {
  730. let texture = self.textures.get(Stage::WHITE_TEXTURE_ID).unwrap();
  731. self.render_box_with_texture(x1, y1, x2, y2, color, *texture)
  732. }
  733. pub fn hline(&mut self, min_x: f32, max_x: f32, y: f32, color: Color, w: f32) {
  734. self.render_box(min_x, y - w / 2., max_x, y + w / 2., color)
  735. }
  736. pub fn vline(&mut self, x: f32, min_y: f32, max_y: f32, color: Color, w: f32) {
  737. self.render_box(x - w / 2., min_y, x + w / 2., max_y, color)
  738. }
  739. pub fn outline(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: Color, w: f32) {
  740. // top
  741. self.render_box(x1, y1, x2, y1 + w, color);
  742. // left
  743. self.render_box(x1, y1, x1 + w, y2, color);
  744. // right
  745. self.render_box(x2 - w, y1, x2, y2, color);
  746. // bottom
  747. self.render_box(x1, y2 - w, x2, y2, color);
  748. }
  749. fn render_text(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
  750. let node = self.scene_graph.get_node(node_id).unwrap();
  751. let text = node.get_property_str("text")?;
  752. let font_size = node.get_property_f32("font_size")?;
  753. let debug = node.get_property_bool("debug")?;
  754. let rect = Self::get_dim(node, layer_rect)?;
  755. let baseline = node.get_property_f32("baseline")?;
  756. let color_prop = node.get_property("color").ok_or(Error::PropertyNotFound)?;
  757. let color_r = color_prop.get_f32(0)?;
  758. let color_g = color_prop.get_f32(1)?;
  759. let color_b = color_prop.get_f32(2)?;
  760. let color_a = color_prop.get_f32(3)?;
  761. let layer_w = layer_rect.w as f32;
  762. let layer_h = layer_rect.h as f32;
  763. let off_x = rect.x / layer_w;
  764. let off_y = rect.y / layer_h;
  765. // Use absolute pixel scale
  766. let scale_x = 1. / layer_w;
  767. let scale_y = 1. / layer_h;
  768. //let model = glam::Mat4::IDENTITY;
  769. let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
  770. glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
  771. let mut uniforms_data = [0u8; 128];
  772. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&self.proj) };
  773. uniforms_data[0..64].copy_from_slice(&data);
  774. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
  775. uniforms_data[64..].copy_from_slice(&data);
  776. assert_eq!(128, 2 * UniformType::Mat4.size());
  777. self.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
  778. //let mut strings = vec![];
  779. //let mut current_str = String::new();
  780. //let mut current_idx = 0;
  781. //for chr in text.chars() {
  782. // let ft_face = self.font_faces[current_idx];
  783. // if ft_face.get_char_index(chr as usize).is_some() {
  784. // }
  785. //}
  786. let mut current_idx = 0;
  787. let mut current_str = String::new();
  788. let mut substrs = vec![];
  789. 'next_char: for chr in text.chars() {
  790. let idx = 'get_idx: {
  791. for i in 0..self.font_faces.len() {
  792. let ft_face = &self.font_faces[i];
  793. if ft_face.get_char_index(chr as usize).is_some() {
  794. break 'get_idx i
  795. }
  796. }
  797. warn!("no font fallback for char: {}", chr);
  798. // Skip this char
  799. continue 'next_char
  800. };
  801. if current_idx != idx {
  802. if !current_str.is_empty() {
  803. // Push
  804. substrs.push((current_idx, current_str.clone()));
  805. }
  806. current_str.clear();
  807. current_idx = idx;
  808. }
  809. current_str.push(chr);
  810. }
  811. if !current_str.is_empty() {
  812. // Push
  813. substrs.push((current_idx, current_str));
  814. }
  815. let mut current_x = 0.;
  816. let mut current_y = baseline;
  817. for (face_idx, text) in substrs {
  818. let face = &self.font_faces[face_idx];
  819. if face.has_fixed_sizes() {
  820. // emojis required a fixed size
  821. //face.set_char_size(109 * 64, 0, 72, 72).unwrap();
  822. face.select_size(0).unwrap();
  823. } else {
  824. face.set_char_size(font_size as isize * 64, 0, 72, 72).unwrap();
  825. }
  826. let hb_font = harfbuzz_rs::Font::from_freetype_face(face.clone());
  827. let buffer = harfbuzz_rs::UnicodeBuffer::new().add_str(&text);
  828. let output = harfbuzz_rs::shape(&hb_font, buffer, &[]);
  829. let positions = output.get_glyph_positions();
  830. let infos = output.get_glyph_infos();
  831. for (position, info) in positions.iter().zip(infos) {
  832. let gid = info.codepoint;
  833. // Index within this substr
  834. // let cluster = info.cluster;
  835. let mut flags = ft::face::LoadFlag::DEFAULT;
  836. if face.has_color() {
  837. flags |= ft::face::LoadFlag::COLOR;
  838. }
  839. face.load_glyph(gid, flags).unwrap();
  840. let glyph = face.glyph();
  841. glyph.render_glyph(ft::RenderMode::Normal).unwrap();
  842. // https://gist.github.com/jokertarot/7583938?permalink_comment_id=3327566#gistcomment-3327566
  843. let bmp = glyph.bitmap();
  844. let buffer = bmp.buffer();
  845. let bmp_width = bmp.width() as usize;
  846. let bmp_height = bmp.rows() as usize;
  847. let bearing_x = glyph.bitmap_left() as f32;
  848. let bearing_y = glyph.bitmap_top() as f32;
  849. //assert_eq!(bmp.pixel_mode().unwrap(), ft::bitmap::PixelMode::Bgra);
  850. //assert_eq!(bmp.pixel_mode().unwrap(), ft::bitmap::PixelMode::Lcd);
  851. //assert_eq!(bmp.pixel_mode().unwrap(), ft::bitmap::PixelMode::Gray);
  852. let pixel_mode = bmp.pixel_mode().unwrap();
  853. let tdata = match pixel_mode {
  854. ft::bitmap::PixelMode::Bgra => {
  855. let mut tdata = vec![];
  856. tdata.resize(4 * bmp_width * bmp_height, 0);
  857. // Convert from BGRA to RGBA
  858. for i in 0..bmp_width*bmp_height as usize {
  859. let idx = i*4;
  860. let b = buffer[idx];
  861. let g = buffer[idx + 1];
  862. let r = buffer[idx + 2];
  863. let a = buffer[idx + 3];
  864. tdata[idx] = r;
  865. tdata[idx + 1] = g;
  866. tdata[idx + 2] = b;
  867. tdata[idx + 3] = a;
  868. }
  869. tdata
  870. }
  871. ft::bitmap::PixelMode::Gray => {
  872. // Convert from greyscale to RGBA8
  873. let tdata: Vec<_> = buffer
  874. .iter()
  875. .flat_map(|coverage| {
  876. let r = (255. * color_r) as u8;
  877. let g = (255. * color_g) as u8;
  878. let b = (255. * color_b) as u8;
  879. let α = ((*coverage as f32) * color_a) as u8;
  880. vec![r, g, b, α]
  881. })
  882. .collect();
  883. tdata
  884. }
  885. _ => panic!("unsupport pixel mode: {:?}", pixel_mode)
  886. };
  887. let (x1, y1, x2, y2) = if face.has_fixed_sizes() {
  888. // Downscale by height
  889. let width = (bmp_width as f32 * font_size) / bmp_height as f32;
  890. let height = font_size;
  891. let x1 = current_x;
  892. let y1 = current_y - height;
  893. let x2 = current_x + width;
  894. let y2 = current_y;
  895. current_x += width;
  896. (x1, y1, x2, y2)
  897. } else {
  898. let (width, height) = (bmp_width as f32, bmp_height as f32);
  899. let off_x = position.x_offset as f32 / 64.;
  900. let off_y = position.y_offset as f32 / 64.;
  901. let x1 = current_x + off_x + bearing_x;
  902. let y1 = current_y - off_y - bearing_y;
  903. let x2 = x1 + width as f32;
  904. let y2 = y1 + height as f32;
  905. let x_advance = position.x_advance as f32 / 64.;
  906. let y_advance = position.y_advance as f32 / 64.;
  907. current_x += x_advance;
  908. current_y += y_advance;
  909. (x1, y1, x2, y2)
  910. };
  911. let texture = self.ctx.new_texture_from_rgba8(bmp_width as u16, bmp_height as u16, &tdata);
  912. self.render_box_with_texture(x1, y1, x2, y2, COLOR_WHITE, texture);
  913. self.ctx.delete_texture(texture);
  914. if debug {
  915. self.outline(x1, y1, x2, y2, COLOR_BLUE, 1.);
  916. }
  917. }
  918. if debug {
  919. self.hline(0., current_x, 0., COLOR_RED, 1.);
  920. }
  921. }
  922. Ok(())
  923. }
  924. fn render_glyph(&mut self, glyph_id: u32, font_size: f32, x: f32, y: f32) -> Result<()> {
  925. Ok(())
  926. }
  927. }
  928. impl EventHandler for Stage {
  929. fn update(&mut self) {
  930. if self.last_draw_time.is_none() {
  931. return
  932. }
  933. // Only allow 20 ms, process as much as we can during that time
  934. let elapsed_since_draw = self.last_draw_time.unwrap().elapsed();
  935. // We're long overdue a redraw. Exit for now
  936. if elapsed_since_draw > Duration::from_millis(20) {
  937. return
  938. }
  939. // The next redraw must happen 20ms since its last one.
  940. // Calculate how much time is remaining until then.
  941. let allowed_time = Duration::from_millis(20) - elapsed_since_draw;
  942. let deadline = Instant::now() + allowed_time;
  943. loop {
  944. let Ok((event, node_id, arg_data, response_fn)) =
  945. self.method_recvr.recv_deadline(deadline)
  946. else {
  947. break
  948. };
  949. let res = match event {
  950. GraphicsMethodEvent::LoadTexture => self.method_load_texture(node_id, arg_data),
  951. GraphicsMethodEvent::DeleteTexture => self.method_delete_texture(node_id, arg_data),
  952. GraphicsMethodEvent::CreateChatView => self.method_create_chatview(node_id, arg_data),
  953. GraphicsMethodEvent::CreateEditBox => self.method_create_editbox(node_id, arg_data),
  954. };
  955. response_fn(res);
  956. }
  957. }
  958. // Only do drawing here. Apps might not call this when minimized.
  959. fn draw(&mut self) {
  960. self.last_draw_time = Some(Instant::now());
  961. let (screen_width, screen_height) = window::screen_size();
  962. // This will make the top left (0, 0) and the bottom right (1, 1)
  963. // Default is (-1, 1) -> (1, -1)
  964. let proj = glam::Mat4::from_translation(glam::Vec3::new(-1., 1., 0.)) *
  965. glam::Mat4::from_scale(glam::Vec3::new(2., -2., 1.));
  966. //let proj = glam::Mat4::IDENTITY;
  967. let scene_graph = self.scene_graph.lock().unwrap();
  968. // We need this because scene_graph must remain locked for the duration of the rendering
  969. let mut render_context = RenderContext {
  970. scene_graph,
  971. ctx: &mut self.ctx,
  972. pipeline: &self.pipeline,
  973. proj,
  974. textures: &self.textures,
  975. font_faces: &self.font_faces,
  976. };
  977. render_context.render_window();
  978. drop(render_context);
  979. }
  980. fn key_down_event(&mut self, keycode: KeyCode, modifiers: KeyMods, repeat: bool) {
  981. let mut scene_graph = self.scene_graph.lock().unwrap();
  982. let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap();
  983. let key = keycode.to_str();
  984. let mut data = vec![];
  985. modifiers.shift.encode(&mut data).unwrap();
  986. modifiers.ctrl.encode(&mut data).unwrap();
  987. modifiers.alt.encode(&mut data).unwrap();
  988. modifiers.logo.encode(&mut data).unwrap();
  989. repeat.encode(&mut data).unwrap();
  990. key.encode(&mut data).unwrap();
  991. win.trigger("key_down", data).unwrap();
  992. }
  993. fn key_up_event(&mut self, keycode: KeyCode, modifiers: KeyMods) {
  994. let mut scene_graph = self.scene_graph.lock().unwrap();
  995. let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap();
  996. let key = keycode.to_str();
  997. let mut data = vec![];
  998. modifiers.shift.encode(&mut data).unwrap();
  999. modifiers.ctrl.encode(&mut data).unwrap();
  1000. modifiers.alt.encode(&mut data).unwrap();
  1001. modifiers.logo.encode(&mut data).unwrap();
  1002. key.encode(&mut data).unwrap();
  1003. win.trigger("key_up", data).unwrap();
  1004. }
  1005. fn mouse_motion_event(&mut self, x: f32, y: f32) {
  1006. let mut scene_graph = self.scene_graph.lock().unwrap();
  1007. let mut data = vec![];
  1008. x.encode(&mut data).unwrap();
  1009. y.encode(&mut data).unwrap();
  1010. let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
  1011. mouse.trigger("move", data).unwrap();
  1012. }
  1013. fn mouse_wheel_event(&mut self, x: f32, y: f32) {
  1014. let mut scene_graph = self.scene_graph.lock().unwrap();
  1015. let mut data = vec![];
  1016. x.encode(&mut data).unwrap();
  1017. y.encode(&mut data).unwrap();
  1018. let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
  1019. mouse.trigger("wheel", data).unwrap();
  1020. }
  1021. fn mouse_button_down_event(&mut self, button: MouseButton, x: f32, y: f32) {
  1022. let mut scene_graph = self.scene_graph.lock().unwrap();
  1023. let mut data = vec![];
  1024. button.to_u8().encode(&mut data).unwrap();
  1025. x.encode(&mut data).unwrap();
  1026. y.encode(&mut data).unwrap();
  1027. let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
  1028. mouse.trigger("button_down", data).unwrap();
  1029. }
  1030. fn mouse_button_up_event(&mut self, button: MouseButton, x: f32, y: f32) {
  1031. let mut scene_graph = self.scene_graph.lock().unwrap();
  1032. let mut data = vec![];
  1033. button.to_u8().encode(&mut data).unwrap();
  1034. x.encode(&mut data).unwrap();
  1035. y.encode(&mut data).unwrap();
  1036. let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
  1037. mouse.trigger("button_up", data).unwrap();
  1038. }
  1039. fn resize_event(&mut self, width: f32, height: f32) {
  1040. let mut data = vec![];
  1041. width.encode(&mut data).unwrap();
  1042. height.encode(&mut data).unwrap();
  1043. let mut scene_graph = self.scene_graph.lock().unwrap();
  1044. let win = scene_graph.lookup_node_mut("/window").unwrap();
  1045. let prop = win.get_property("screen_size").unwrap();
  1046. prop.set_f32(0, width).unwrap();
  1047. prop.set_f32(1, height).unwrap();
  1048. win.trigger("resize", data).unwrap();
  1049. }
  1050. }
  1051. pub fn run_gui(scene_graph: SceneGraphPtr) {
  1052. #[cfg(target_os = "android")]
  1053. {
  1054. android_logger::init_once(
  1055. android_logger::Config::default().with_max_level(LevelFilter::Debug).with_tag("fagman"),
  1056. );
  1057. }
  1058. #[cfg(target_os = "linux")]
  1059. {
  1060. let term_logger = simplelog::TermLogger::new(
  1061. simplelog::LevelFilter::Debug,
  1062. simplelog::Config::default(),
  1063. simplelog::TerminalMode::Mixed,
  1064. simplelog::ColorChoice::Auto,
  1065. );
  1066. simplelog::CombinedLogger::init(vec![term_logger]).expect("logger");
  1067. }
  1068. let mut conf = miniquad::conf::Conf {
  1069. high_dpi: true,
  1070. window_resizable: true,
  1071. platform: miniquad::conf::Platform {
  1072. linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
  1073. wayland_use_fallback_decorations: false,
  1074. ..Default::default()
  1075. },
  1076. ..Default::default()
  1077. };
  1078. let metal = std::env::args().nth(1).as_deref() == Some("metal");
  1079. conf.platform.apple_gfx_api =
  1080. if metal { conf::AppleGfxApi::Metal } else { conf::AppleGfxApi::OpenGl };
  1081. miniquad::start(conf, || Box::new(Stage::new(scene_graph)));
  1082. }