From 037930fec03a9972355b36db8b113bb9740a4a85 Mon Sep 17 00:00:00 2001 From: whosit Date: Thu, 27 May 2021 08:46:57 +0300 Subject: [PATCH] use waypoint_lib --- init.lua | 68 ++++------- textures/arrow_000.png | Bin 0 -> 801 bytes textures/arrow_010.png | Bin 0 -> 932 bytes textures/arrow_020.png | Bin 0 -> 933 bytes textures/arrow_030.png | Bin 0 -> 900 bytes textures/arrow_040.png | Bin 0 -> 939 bytes textures/arrow_050.png | Bin 0 -> 925 bytes textures/arrow_060.png | Bin 0 -> 935 bytes textures/arrow_070.png | Bin 0 -> 887 bytes textures/arrow_080.png | Bin 0 -> 898 bytes textures/waypoint.png | Bin 0 -> 501 bytes waypoint.svg | 68 +++++++++++ waypoint_lib.lua | 255 +++++++++++++++++++++++++++++++++++++++++ 13 files changed, 348 insertions(+), 43 deletions(-) create mode 100644 textures/arrow_000.png create mode 100644 textures/arrow_010.png create mode 100644 textures/arrow_020.png create mode 100644 textures/arrow_030.png create mode 100644 textures/arrow_040.png create mode 100644 textures/arrow_050.png create mode 100644 textures/arrow_060.png create mode 100644 textures/arrow_070.png create mode 100644 textures/arrow_080.png create mode 100644 textures/waypoint.png create mode 100644 waypoint.svg create mode 100644 waypoint_lib.lua diff --git a/init.lua b/init.lua index adf6b0e..4cd28cb 100644 --- a/init.lua +++ b/init.lua @@ -5,7 +5,10 @@ local TARGET_ABOVE = false -- place waypoint inside the block or above it local POINT_TO_OBJECTS = false -- unimplemented local POINT_TO_LIQUIDS = true local COMPASS_RANGE = 180 +local WAYPOINT_ICON = "waypoint.png" +local WAYPOINT_SCALE = {x=-1/16*9,y=-1} +local waypoint_lib = dofile(minetest.get_modpath("waypoint_announce") .. "/waypoint_lib.lua") -- internal mod state local player_waypoints = {} -- store a current player waypoint to see if it needs to be updated @@ -66,16 +69,6 @@ local function get_compass_meta_owner(meta) end --- local function set_compass_meta_pos(meta, pos) --- local pos_hash = minetest.hash_node_position(pos) --- meta:set_int("waypoint_compass:position", pos_hash) --- end - - --- local function get_compass_meta_pos(meta) --- return minetest.get_position_from_hash(meta:get_int("waypoint_compass:position")) --- end - local function set_waypoint_at_pointed_place(itemstack, pointed_thing) if pointed_thing and pointed_thing.type == "node" then local pointed_pos = TARGET_ABOVE and pointed_thing.above or pointed_thing.under @@ -90,27 +83,11 @@ local function set_waypoint_at_pointed_place(itemstack, pointed_thing) end --- return first thing player is pointing at -local function raycast_crosshair(player, range) - local p_pos = player:get_pos() - local p_eye_height = player:get_properties().eye_height - local p_eye_pos = { x = p_pos.x, y = p_pos.y + p_eye_height, z = p_pos.z } - local to = vector.add(p_eye_pos, vector.multiply(player:get_look_dir(), range)) - local ray = minetest.raycast(p_eye_pos, to, POINT_TO_OBJECTS, POINT_TO_LIQUIDS) - local pointed_thing = ray:next() - return pointed_thing - -- while pointed_thing do - -- print(pointed_thing.type, minetest.pos_to_string(pointed_thing.under)) - -- pointed_thing = ray:next() - -- end -end - - local function hide_hud_waypoint(player) local player_name = player:get_player_name() - local hud_id = player_waypoints[player_name].hud_id + local hud = player_waypoints[player_name] player_waypoints[player_name] = nil - player:hud_remove(hud_id) + hud:hide(player) end @@ -121,24 +98,29 @@ local function show_hud_waypoint(player, compass_item_meta) -- do not show unset compass position return end + -- Show this waypoint local waypoint_name = get_compass_meta_label(compass_item_meta) local waypoint_color = get_compass_meta_color(compass_item_meta) - local hud_id = player:hud_add({ - hud_elem_type = "waypoint", - name = waypoint_name, - text = "m", - precision= COMPASS_PRECISION, - number = waypoint_color, - world_pos = waypoint_pos, - }) + local hexcolor = ("#%06X"):format(waypoint_color) + + local size = {x=-9, y=-16} + local alignment = {x=100/9*1.47,y=100/16*1.63} -- near compass in your hand + + local waypoint = waypoint_lib.WaypointHUD:new(player, waypoint_pos, + waypoint_name, waypoint_color, + WAYPOINT_ICON, WAYPOINT_SCALE, hexcolor, + size, alignment, "arrow_%03d.png", hexcolor, 9, + true) + + waypoint:show(player) -- store HUD elemnt id to remove it later - if not player_waypoints[player_name] then - player_waypoints[player_name] = {} + if player_waypoints[player_name] then + minetest.log("error","[MOD] waypoint_compass: " .. + player:get_player_name() .. + " got their HUD stuck on screen?") end - --print("hud_id add", hud_id) - player_waypoints[player_name].pos = waypoint_pos - player_waypoints[player_name].hud_id = hud_id + player_waypoints[player_name] = waypoint end @@ -155,7 +137,7 @@ local function update_hud_waypoint(player, itemstack, force) local waypoint_pos = get_compass_meta_pos(meta) -- remove different waypoint if it exists if player_waypoints[player_name] and - (player_waypoints[player_name].pos ~= waypoint_pos + (player_waypoints[player_name].point_pos ~= waypoint_pos or force or not get_compass_meta_is_set(meta)) then @@ -260,7 +242,7 @@ local function compass_use_callback(itemstack, user, pointed_thing) if user:get_player_control()["sneak"] then if pointed_thing.type == "nothing" then if user and user:is_player() then - pointed_thing = raycast_crosshair(user, COMPASS_RANGE) + pointed_thing = waypoint_lib.raycast_crosshair(user, COMPASS_RANGE, POINT_TO_OBJECTS, POINT_TO_LIQUIDS) end end set_waypoint_at_pointed_place(itemstack, pointed_thing) diff --git a/textures/arrow_000.png b/textures/arrow_000.png new file mode 100644 index 0000000000000000000000000000000000000000..93a79f8bc194612a6642fdb859c0b57cafa6a167 GIT binary patch literal 801 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkFdh=lvRq4O~jhr?KJ}f<9kmR$B>MBZ>MkcyB#3n zz;Ak_QDLd#G@hwSE)jEdbOgUGp3AUOGBDk(C7^yOv#^lU-&tX~;%PIC6Ki2!l>-hlY;ZmM%It~@&#E9%HkYS43*2W+aPU~q!^q!!e>uOM z+x$iQni_uCvMoFpyT(6of1}=8GeOyF3w_ewENR>&M(L$e`=E2L6O?7S-dGiJ{OnIh<^~+r1?wa zGq;VWf$Qv~x<++QyO?WBXT&Q^UQlqF_xsDF5dWilnEnfiwADQ4uAWoWxi0;7t4s`*JhgO9)V>A(_<#3oe^OEOqa(iNX@`7I%}vwdb=%x~ z%n~_amBAzP_B9L}&Kz_}iWBgA^G|!9&k4(Ze*c+X3Uh?T)HfV9t)C}5Z|aYe6W%^z z`6cu5;Z#}K4?8UyEz{!up5ZAz%4s3P*M9h60g!TM{KIO0xJ!RQf-flbsg}4#l%yn< zq*^5xr2;7iBLgEtT?12HBeM`g6DtEVDoc5!lIL8@MUQTpt6Hc~)E44$rjF6*2UngIOyE-C;3 literal 0 HcmV?d00001 diff --git a/textures/arrow_010.png b/textures/arrow_010.png new file mode 100644 index 0000000000000000000000000000000000000000..5a93302b0802ebb696e35c4a60e90acde2ae252b GIT binary patch literal 932 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 literal 0 HcmV?d00001 diff --git a/textures/arrow_040.png b/textures/arrow_040.png new file mode 100644 index 0000000000000000000000000000000000000000..0638941704e86f1e114da8f491312da050845ac5 GIT binary patch literal 939 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkFdh=lvRq4P1J{>tQM%L($mE;B;(%OY2F?oi4tw| zCDV@;&T_cqc4otyv@BLZ$r(<1Dkt7K3bH(078(#3l;YaW#pTpdCMx1qqIl6u*QJR^ ze=BDf%Tyh8ZtbHNj-597ye;6=8>eN@&pflaJ->L~_rDhZk27+Ez~aION54IPtkL{6 zZrh{9qOOZ}_m=2gI5ElN#KFUS^Mn>jq^o>cIcK@_#dBVtpXO}~^yg6Ynvt}vPVZ>V zCkr9Hl;>B-ig4w-sw)Fe9`c`d@s~?iMtRHTkY)P690Oc8 zb$3_vOtC)kl#lu2t>x1Kfyz9)UB!R8y%N?~qN_D$W%R4d=UYm{`~v;f1b)&e(pXwQ zt88_qPq}B+a+!f0y`r#mP9-ji=rsM~6G|cwpYA zIeATdN3$3IQGU$7!lA_?^+&y$navr+e&(2?@{3O^GfGX-xpl%M%HFDDwlhy|!1g5z zxKf3ucNpq3I7sO)UmX=R`I4*p>f^teezP!d3HTY9$`j;heC6YjJO3DNmYlgBo7x?> zZT5P0{p)k0)~$RbXsjg2u-0qKnC}Q!>*kacf97v8)7YkObKfoS#-wo>-L1P+nfH gmzkGcoSayYs+V7sKKq@G6i^X^r>mdKI;Vst0B^5&asU7T literal 0 HcmV?d00001 diff --git a/textures/arrow_050.png b/textures/arrow_050.png new file mode 100644 index 0000000000000000000000000000000000000000..be52a619caa926b8e3e1ea6bea65a387542f7d51 GIT binary patch literal 925 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkFdh=lvRq4P1J{>tQM##+tbA{B;(%O>)swAfilNG zzPEUVTQ4EC(H2 zH7`18Oi`K4CaOBsX?CH^`}M7hGqy8{#V?-|HbE8PcwEOP1+bCbS5uKQ*$D- zMWj35U6(Z5aGtY?!l5CL)l*I-E&mvN#J8y@(09|$Ol!$07d-6Q9_dD=9g9sVoOJ!q z2MIexHj9k7JMMDgKOIyeS*_OQ2tH-AD}Ka%!;{xB`pSCSRl&=(o(kqiB)i!(J6|zQ zFrW6aV_s&!rQ+1C^&-cubJKN~?nyea^y{jC%}z!ttf3leRya!j z3SG{1L}Plval3aZqQ@%^mbXt_YGj%jVcZ(3x13{x(zQbUogtSFd2HGkIsK|t<)h1{ z8nItCXn$LM{-L2_i`lDAr(b*das>s?oiF?S|4F&c0c)$m$+w&8hFCZgMZo!m`hq=77Lf3Hw zH(tKOxb5Qn<#D_(S4=vheCh1j!$nb-uCB3K+QG+l=3I0C?Yy}c*aR2xwEtv2pn2@s zX~lPwr*+tfeB{08SC{l@!z?o=8S{^m%n#eV+Ufr4{=R?ji`@$^9yso@R{lWpA>PZt zh}RM8KKe=iH|KGs+MNxL+>QWKqH2k2L`h0wNvc(HQ7VvPFfuSQ)HN{GH8Kk^G_f); zvobQ&HZZUBuF?hQAxvXNS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkFdh=lvRq4P1J{>tQM%L)YHW=B;(%OYu+9qfeh^* z^N(5gozu{=TGdV2f~<+13@YExJ`}wW3=V zctnULx+ZzdoGENOLE+T(KhY6JFL!vPyRG;feed|sbGF~(-mxAw;5ls2^S^8Ek(;xH z9!)8meBSES#)|Gk^!CdMZB7wP7#oP1*846i@? zr&~>Ss<{&6#`tpoy=`(#CBB8TllRQ3U$H;&xF?@$NbpgqJxeTf__bFY>F;N{RM5hE z!@HrZuwU($_|9|2Kdsh%=<)YaYcJaB*j^fVmn+Lh@$9#lXqOJNQ;US>Z|mZ&apW^y z9#I`?<+gf{pJd@lWt!p4;<$Rb+nJQ}(UVWgjPe-FVtxdr9kprB$qlKfS-Qg5~1jV-e38 zC*3$)u&?Uyr{Afa%X7NiHhgXmc=YeAZZ4(g_zlqNAG6-;9{}#)fWD^zpjD7vF}054~FjAoIN%V zg_6CCzcQ>;(T%+WN(4NIf0+Ma(HD2Cx_AC=1~5&kmbgZgq$HN4S|t~y0x1R~10zFS z15;fivk*fQD+4ntBSUQi11kdqvCPJ!C>nC}Q!>*kacf97v8)7YkObKfoS#-wo>-L1 kP+nfHmzkGcoSayYs+V7sKKq@G6i^X^r>mdKI;Vst09R6b3;+NC literal 0 HcmV?d00001 diff --git a/textures/arrow_070.png b/textures/arrow_070.png new file mode 100644 index 0000000000000000000000000000000000000000..2bb7a8c30dbdcaa5fa2430884876812127db81bc GIT binary patch literal 887 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkFdh=lvRq4P1J{>tQM%r)zif>B;(%OYt|m2g$&0( zzOTG@eCP8!)$KamB1IE2G*4(Q?BUW{Qc$3Id+~L-9VQ|oq89}ed088Syq!awcssij zQW63qIRgW>H<<|fzF+UCt1N$_mgDRH9Cp6{@BbJ6D>z`la~OpFIbYku@0#}b!NZ4- z1qIYqR9s!;{ZE|V^F&OdaKp!sA3B7URUBtEbaZs+Fh)*tVNv1y;A!B(-e328`ab5V zYt%d^@hE0G8MU-5@e~qN_vDcm7r(w~L(J)e$B#ebo~#g8Ft4mFoqxv`*$p=icxG+* zP*|`r=k~$Fs%_p~ESgSCMl30v9>Rh~r%K-)koa!td;ZN;{aU6+jM*7WwGR4aah#l> z5tE;0Hz(M<32!UN3n?Y^e5#ca(8=>EBG^(s-}FPB{QNPL{B zY4YjL$@kY^vwmi_TD0ZIIn!(6zqj3d^I+v#wY{^{?bcP_(o#RKaQvi*x!uu4jdIbu zudM$Q|8vf{RZ%^kC$u%`|6($`oci?pi_7vKJ#E9fnLbYC4w)PM7|NE(jD7x)Ds`lp6^Mx}f?vn=Hb71(Dm2ptyLc~i%UJ{u9`mix$5x~ z)AacSif&&o3+*&~w~2T8p2`SE^Gz;&#!L5qERH;F>>|&8s_^mipySbbn>H@lU)t^S zKtuGjDEo(x(~R>a+7f~2k9Hl?78S$qn@&Dn2~1?)FK#IZ0z{pV7 zz*N`BEX2^n%D~LZ$WYtBz{g5-u&wghk1ysb~>FVdQ&MBb@0BLk&k^lez literal 0 HcmV?d00001 diff --git a/textures/arrow_080.png b/textures/arrow_080.png new file mode 100644 index 0000000000000000000000000000000000000000..22fdd12dd8892502701984272300cf5dc1f4eaeb GIT binary patch literal 898 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5SkFdh=lvRq4P1J{>tQM##z|+MsB;(%OE505ffii6$ z(`9l^bTxU!9ogJOZYZ5~?Y84>j$&~Q(B-=Ih4F2Z*;cJARhJ0~j@?`>XM9rx8@G0w z?ee_T8X#n9{QX?dIg9({?`|huT9j09tnkj9`=1W&JpW(joo#|dTOtS@$lYL-Q#Ely)oq|ezw)JjHc^G)_JUn!8R^2v*7Ux+eo=!(T3LiV9bb`n6S;qu5 z?`b{WeC<4fY85BEjZ~+K=R7N&dM-Qcf6>!ZflkI;89~Wai+|rz&#$}0nYXcd*V3b( zzZr$Dx3knb66(=xwX9U>u!ecY@?|oG4O)7_nU`-feQcPwBAQp}sK)h7{fEo-S4^z7 zXixcTZnw5hHej!Z(Xr55E41=$-dkMstNpD#@3Q#UmC>b2C)w9sh{||=G~Q)@<&AT% z^k)69c=BPcIFEss);1YG6BXFK+7+P10i!=>&Y2a~I` zS4C%AvPutBJ>;p>}4bxR*XVz(_Y%${-e`lkCQXC2uHOm3E rrERK(!v>gTe~DWM4fWx-*L literal 0 HcmV?d00001 diff --git a/textures/waypoint.png b/textures/waypoint.png new file mode 100644 index 0000000000000000000000000000000000000000..5c22d1509e8cf398fda66918d55e7e0ee34feaaa GIT binary patch literal 501 zcmVpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10fI?H zK~y-6m6J_w+CUV?|8g}(f??h}M@hH60ULiDhduZX{g4tRR{*tlXewdM1wcyET{br3 zi9quBb#JENhCQ zkh-p=u4`E=7LsLILqv{)Ye*iwt=-)!Z6$h03af#w%^mXEdWT+>-8Si>-E_NtJMnKZucQ*n&$g# zHuL8iOs7-dG|e{vxF8}|Rn^J+%d!+>j05l<06;|7Ns>74{eQ*Ydx@gR5z*!IMxin0 zHjd+?P0F&AD2kjh<_8Y^hp^x8UlP&dWHM>;JQr)NSZgKEa~Y4v4G}&5O@1YQ&OmGZ rnVEknrM60`Ei>O~tv>-6{CoTd`g7U;g$_PY00000NkvXXu0mjfUaH@~ literal 0 HcmV?d00001 diff --git a/waypoint.svg b/waypoint.svg new file mode 100644 index 0000000..27e29b7 --- /dev/null +++ b/waypoint.svg @@ -0,0 +1,68 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/waypoint_lib.lua b/waypoint_lib.lua new file mode 100644 index 0000000..b2ba0db --- /dev/null +++ b/waypoint_lib.lua @@ -0,0 +1,255 @@ +local WAYPOINT_PRECISION = 1 -- set to 1 to show whole number or 10 for 1 decimal +local UPDATE_INTERVAL = 0.22 + + +-- get actual eye_pos of the player (including eye_offset) +local function player_get_eye_pos(player) + local p_pos = player:get_pos() + local p_eye_height = player:get_properties().eye_height + p_pos.y = p_pos.y + p_eye_height + local p_eye_pos = p_pos + local p_eye_offset = vector.multiply(player:get_eye_offset(), 0.1) + local yaw = player:get_look_horizontal() + p_eye_pos = vector.add(p_eye_pos, vector.rotate_around_axis(p_eye_offset, {x=0,y=1,z=0}, yaw)) + return p_eye_pos +end + + +-- return first thing player is pointing at +local function raycast_crosshair(player, range, point_to_objects, point_to_liquids) + local p_eye_pos = player_get_eye_pos(player) + local to = vector.add(p_eye_pos, vector.multiply(player:get_look_dir(), range)) + local ray = minetest.raycast(p_eye_pos, to, point_to_objects, point_to_liquids) + local pointed_thing = ray:next() + while pointed_thing do + if pointed_thing.type == "object" and pointed_thing.ref == player then + -- exclude the player themselves from the raycast + pointed_thing = ray:next() + else + return pointed_thing + end + end + -- FIXME return "nothing" pointed thing? + return nil +end + + +-- get position and thing that player is pointing at or nil +local function get_pointed_position(player, range, point_to_objects, point_to_liquids) + local pointed_thing = raycast_crosshair(player, range, point_to_objects, point_to_liquids) + local pointed_pos = nil + if pointed_thing then + if pointed_thing.type == "node" then + -- middle between "above" and "under" + pointed_pos = vector.multiply(vector.add(pointed_thing.above, pointed_thing.under), 0.5) + elseif pointed_thing.type == "object" then + -- TODO point at the middle of collision box? (or not, ground may be better) + pointed_pos = pointed_thing.ref:get_pos() + end + end + return pointed_pos, pointed_thing +end + + +local function round(x) + local f = math.floor(x) + if (x == f) or (x % 2.0 == 0.5) then + return f + else + return math.floor(x + 0.5) + end +end + + +local function get_texture_rotation_for_direction(dir, quad_steps) + -- angle relative to player position + local angle = math.atan2(dir.x, dir.z) + local pi = math.pi + -- snap/round to increments and convert to degrees + local bias = 1/quad_steps/2 -- add bias to floor into correct quardant + local angle_quad = math.floor(angle/(2*pi) * 4 + bias) * (360 / 4) % 360 + local angle_quad_map = {[0] = "I", [90] = "R270", [180] = "R180", [270] = "R90"} + local step_size = 90/quad_steps + local angle_quad_step = (round((math.deg(angle) - angle_quad)/step_size) * step_size) % 90 + return angle_quad_step, angle_quad_map[angle_quad] +end + +-------------------------------------------------------------------------------- +-- [[ Waypoint HUD element with distance, label an icon above it ]] -- +local IconWaypointHUD = {} +function IconWaypointHUD:new(point_pos, label, label_color, icon, icon_scale, icon_color) + local w = { + hud_id_label = nil, + hud_id_icon = nil, + } + self.__index = self + setmetatable(w, self) + + w.huddef_label = { + hud_elem_type = "waypoint", + name = label, + text = "m", -- distance suffix + precision = WAYPOINT_PRECISION, -- TODO make this configurable? + number = label_color, + world_pos = point_pos, + offset = {x=0,y=0}, + alignment = {x=0, y=1}, -- move down + } + + w.huddef_icon = { + hud_elem_type = "image_waypoint", + scale = icon_scale, + text = icon .. "^[multiply:" .. icon_color, + alignment = {x=0,y=-1}, + world_pos = point_pos, + offset = {x=0,y=0}, + --name = name, + --precision = WAYPOINT_PRECISION, + --number = waypoint_color, + } + + return w +end + + +function IconWaypointHUD:show(player) + --self.player_name = player:get_player_name() + self.hud_id_label = player:hud_add(self.huddef_label) + self.hud_id_icon = player:hud_add(self.huddef_icon) +end + + +function IconWaypointHUD:hide(player) + player:hud_remove(self.hud_id_label) + player:hud_remove(self.hud_id_icon) +end + + +function IconWaypointHUD:update(player) + error("No reason to call IconWaypointHUD:update(), fix your code") +end + +-------------------------------------------------------------------------------- +-- [[ Just an arrow HUD element. Can be turned any direction with update() ]] -- +local CompassHUD = {} +function CompassHUD:new(size, alignment, direction, icon_format, icon_color, quad_steps) + local c = { + icon_format = icon_format, + icon_color = icon_color, + quad_steps = quad_steps, + -- TODO have a callback to auto-update the direction? + } + self.__index = self + setmetatable(c, self) + + local texture = c:get_texture(direction) + + c.huddef_compass = { + hud_elem_type = "compass", + size = size, + text = texture, + alignment = alignment, + dir = 1, + } + + return c +end + + +function CompassHUD:get_texture(direction) + local angle_quad_step, rotation_t = get_texture_rotation_for_direction(direction, self.quad_steps) + + local texture = self.icon_format:format(angle_quad_step) .. "^[transform" .. rotation_t .. "^[multiply:" .. self.icon_color + return texture +end + + +function CompassHUD:show(player) + --self.player_name = player:get_player_name() + self.hud_id_compass = player:hud_add(self.huddef_compass) +end + + +function CompassHUD:hide(player) + player:hud_remove(self.hud_id_compass) +end + + +function CompassHUD:update(player, direction) + player:hud_change(self.hud_id_compass, "text", self:get_texture(direction)) +end + +-------------------------------------------------------------------------------- + +local WaypointHUD = {} +function WaypointHUD:new(player, point_pos, + label, label_color, + point_icon, point_icon_scale, point_color, + size, alignment, arrow_icon_format, arrow_icon_color, quad_steps, + do_auto_update) + local w = { + point_pos = point_pos, + do_auto_update = do_auto_update, + auto_update_job = nil, + } + self.__index = self + setmetatable(w, self) + + w.waypoint_hud = IconWaypointHUD:new(point_pos, label, label_color, point_icon, point_icon_scale, point_color) + + local d = vector.subtract(point_pos, player:get_pos()) + w.compass_hud = CompassHUD:new(size, alignment, d, arrow_icon_format, arrow_icon_color, quad_steps) + + return w +end + + +function WaypointHUD:show(player) + self.waypoint_hud:show(player) + self.compass_hud:show(player) + self:update(player) -- FIXME? needed to start auto update +end + + +function WaypointHUD:hide(player) + self.waypoint_hud:hide(player) + self.compass_hud:hide(player) + if self.auto_update_job then + self.auto_update_job.cancel() + self.auto_update_job = nil + end +end + + +function WaypointHUD:update(player) + local direction = vector.subtract(self.point_pos, player:get_pos()) + self.compass_hud:update(player, direction) + if self.do_auto_update then + local player_name = player:get_player_name() + local job = minetest.after(UPDATE_INTERVAL, + function() + local player = minetest.get_player_by_name(player_name) + if player then + self:update(player) + end + end + ) + self.auto_update_job = job + end +end + + + +-------------------------------------------------------------------------------- + +waypoint_lib = { + raycast_crosshair = raycast_crosshair, + get_pointed_position = get_pointed_position, + player_hud_add_waypoint_compass = player_hud_add_waypoint_compass, + player_hud_update_waypoint_compass = player_hud_update_waypoint_compass, + IconWaypointHUD = IconWaypointHUD, + CompassHUD = CompassHUD, + WaypointHUD = WaypointHUD, +} + +return waypoint_lib