z_mirror/PipeVisualizer
git clone https://git.raiguard.me/z_mirror/PipeVisualizer
9371b54
2.0
1local flib_bounding_box =require ( "__flib__/bounding-box" ) 2local flib_position =require ( "__flib__/position" ) 3 4local iterator =require ( "__PipeVisualizer__/scripts/iterator" ) 5 6-- In the source code, 200 is defined as the maximum viewable distance, but in reality it's around 220 7-- Map editor is 3x that, but we will ignore that for now 8-- Add five for a comfortable margin 9local max_overlay_size =220 + 5 10 11--- @alias UnitNumber uint 12 13--- @class Overlay 14--- @field background RenderObjectID 15--- @field dimensions DisplayResolution 16--- @field last_position MapPosition? 17--- @field player LuaPlayer 18 19--- @param self Overlay 20--- @param position MapPosition 21local function get_areas ( self , position ) 22local dimensions =self . dimensions 23local last_position =self . last_position 24if not last_position then 25return { flib_bounding_box . from_dimensions ( position , dimensions . width , dimensions . height ) } 26end 27local position_x =position . x 28local position_y =position . y 29local radius_x =dimensions . width / 2 30local radius_y =dimensions . height / 2 31 32local delta =flib_position . sub ( position , last_position ) 33--- @type BoundingBox[] 34local areas ={} 35 36if delta . x < 0 then 37areas [ # areas + 1 ] ={ 38left_top ={ 39x =position_x - radius_x , 40y =position_y - radius_y , 41} , 42right_bottom ={ 43x =last_position . x - radius_x , 44y =position_y + radius_y , 45} , 46} 47elseif delta . x > 0 then 48areas [ # areas + 1 ] ={ 49left_top ={ 50x =last_position . x + radius_x , 51y =position_y - radius_y , 52} , 53right_bottom ={ 54x =position_x + radius_x , 55y =position_y + radius_y , 56} , 57} 58end 59 60if delta . y < 0 then 61areas [ # areas + 1 ] ={ 62left_top ={ 63x =position_x - radius_x , 64y =position_y - radius_y , 65} , 66right_bottom ={ 67x =position_x + radius_x , 68y =last_position . y - radius_y , 69} , 70} 71elseif delta . y > 0 then 72areas [ # areas + 1 ] ={ 73left_top ={ 74x =position_x - radius_x , 75y =last_position . y + radius_y , 76} , 77right_bottom ={ 78x =position_x + radius_x , 79y =position_y + radius_y , 80} , 81} 82end 83 84return areas 85end 86 87--- @param player LuaPlayer 88--- @return DisplayResolution 89local function get_dimensions ( player ) 90local resolution =player . display_resolution 91local divisor =math . max ( resolution . width , resolution . height ) / max_overlay_size 92resolution . width =resolution . width / divisor 93resolution . height =resolution . height / divisor 94return resolution 95end 96 97--- @param self Overlay 98--- @param area BoundingBox 99local function visualize_area ( self , area ) 100local entities =self . player . surface . find_entities_filtered ( { 101area =area , 102force =self . player . force , 103type ={ 104"assembling-machine" , 105"boiler" , 106"fluid-turret" , 107"furnace" , 108"generator" , 109"infinity-pipe" , 110"inserter" , 111"lab" , 112"loader" , 113"loader-1x1" , 114"mining-drill" , 115"offshore-pump" , 116"pipe" , 117"pipe-to-ground" , 118"pump" , 119"reactor" , 120"rocket-silo" , 121"storage-tank" , 122} , 123} ) 124for _ , entity in pairs ( entities ) do 125iterator . request ( entity , self . player . index , true ) 126end 127end 128 129--- @param self Overlay 130local function update_overlay ( self ) 131local position =flib_position . floor ( self . player . position ) 132if self . last_position and flib_position . eq ( position , self . last_position ) then 133return 134end 135rendering . set_target ( self . background , position ) 136rendering . set_x_scale ( self . background , self . dimensions . width ) 137rendering . set_y_scale ( self . background , self . dimensions . height ) 138 139local areas =get_areas ( self , position ) 140 141self . last_position =position 142 143for _ , area in pairs ( areas ) do 144visualize_area ( self , area ) 145end 146end 147 148--- @param player LuaPlayer 149--- @return Overlay 150local function create_overlay ( player ) 151local background =rendering . draw_sprite ( { 152sprite ="pv-entity-box" , 153tint ={} , 154render_layer ="191" , 155target =player . position , 156surface =player . surface , 157players ={ player } , 158} ) 159--- @type Overlay 160local self ={ 161background =background , 162dimensions =get_dimensions ( player ), 163player =player , 164} 165global . overlay [ player . index ] =self 166return self 167end 168 169--- @param self Overlay 170local function destroy_overlay ( self ) 171rendering . destroy ( self . background ) 172iterator . clear_all ( self . player . index ) 173global . overlay [ self . player . index ] =nil 174end 175 176--- @param e EventData.CustomInputEvent|EventData.on_lua_shortcut 177local function on_toggle_overlay ( e ) 178if ( e . input_name or e . prototype_name ) ~= "pv-toggle-overlay" then 179return 180end 181local player =game . get_player ( e . player_index ) 182if not player then 183return 184end 185local entity =player . selected 186if entity and entity . prototype . belt_speed and script . active_mods [ "belt-visualizer" ] then 187return 188end 189local cursor_stack =player . cursor_stack 190if cursor_stack and cursor_stack . valid_for_read and ( cursor_stack . is_blueprint_book or cursor_stack . is_blueprint ) then 191return 192end 193local self =global . overlay [ e . player_index ] 194if self then 195destroy_overlay ( self ) 196else 197local overlay =create_overlay ( player ) 198iterator . clear_all ( e . player_index ) 199update_overlay ( overlay ) 200end 201player . set_shortcut_toggled ( "pv-toggle-overlay" , global . overlay [ e . player_index ] ~= nil ) 202end 203 204--- @param e EventData.on_player_changed_position 205local function on_player_changed_position ( e ) 206local self =global . overlay [ e . player_index ] 207if self then 208update_overlay ( self ) 209end 210end 211 212--- @param e EventData.on_player_display_resolution_changed 213local function on_player_display_resolution_changed ( e ) 214if not global . overlay then 215return 216end 217local self =global . overlay [ e . player_index ] 218if not self then 219return 220end 221self . dimensions =get_dimensions ( self . player ) 222self . last_position =nil 223update_overlay ( self ) 224end 225 226local overlay ={} 227 228function overlay . on_init () 229--- @type table<uint, Overlay> 230global . overlay ={} 231end 232 233overlay . events ={ 234[ defines . events . on_lua_shortcut ] =on_toggle_overlay , 235[ defines . events . on_player_changed_position ] =on_player_changed_position , 236[ defines . events . on_player_display_resolution_changed ] =on_player_display_resolution_changed , 237[ "pv-toggle-overlay" ] =on_toggle_overlay , 238} 239 240return overlay