1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
@tool
extends Control
const HT_Util = preload("../../util/util.gd")
const HTerrain = preload("../../hterrain.gd")
const HTerrainData = preload("../../hterrain_data.gd")
const HT_MinimapOverlay = preload("./minimap_overlay.gd")
const HT_MinimapShader = preload("./minimap_normal.gdshader")
# TODO Can't preload because it causes the plugin to fail loading if assets aren't imported
#const HT_WhiteTexture = preload("../icons/white.png")
const WHITE_TEXTURE_PATH = "res://addons/zylann.hterrain/tools/icons/white.png"
const MODE_QUADTREE = 0
const MODE_NORMAL = 1
@onready var _popup_menu : PopupMenu = $PopupMenu
@onready var _color_rect : ColorRect = $ColorRect
@onready var _overlay : HT_MinimapOverlay = $Overlay
var _terrain : HTerrain = null
var _mode := MODE_NORMAL
var _camera_transform := Transform3D()
func _ready():
if HT_Util.is_in_edited_scene(self):
return
_set_mode(_mode)
_popup_menu.add_item("Quadtree mode", MODE_QUADTREE)
_popup_menu.add_item("Normal mode", MODE_NORMAL)
func set_terrain(node: HTerrain):
if _terrain != node:
_terrain = node
set_process(_terrain != null)
func set_camera_transform(ct: Transform3D):
if _camera_transform == ct:
return
if _terrain == null:
return
var data = _terrain.get_data()
if data == null:
return
var to_local := _terrain.get_internal_transform().affine_inverse()
var pos := _get_xz(to_local * _camera_transform.origin)
var size := Vector2(data.get_resolution(), data.get_resolution())
pos /= size
var dir := _get_xz(to_local.basis * (-_camera_transform.basis.z)).normalized()
_overlay.set_cursor_position_normalized(pos, dir)
_camera_transform = ct
static func _get_xz(v: Vector3) -> Vector2:
return Vector2(v.x, v.z)
func _gui_input(event: InputEvent):
if event is InputEventMouseButton:
if event.pressed:
match event.button_index:
MOUSE_BUTTON_RIGHT:
_popup_menu.position = get_screen_position() + event.position
_popup_menu.popup()
MOUSE_BUTTON_LEFT:
# Teleport there?
pass
func _process(delta):
if _terrain != null:
if _mode == MODE_QUADTREE:
queue_redraw()
else:
_update_normal_material()
func _set_mode(mode: int):
if mode == MODE_QUADTREE:
_color_rect.hide()
else:
var mat := ShaderMaterial.new()
mat.shader = HT_MinimapShader
_color_rect.material = mat
_color_rect.show()
_update_normal_material()
_mode = mode
queue_redraw()
func _update_normal_material():
if _terrain == null:
return
var data : HTerrainData = _terrain.get_data()
if data == null:
return
var normalmap = data.get_texture(HTerrainData.CHANNEL_NORMAL)
_set_if_changed(_color_rect.material, "u_normalmap", normalmap)
var globalmap : Texture
if data.has_texture(HTerrainData.CHANNEL_GLOBAL_ALBEDO, 0):
globalmap = data.get_texture(HTerrainData.CHANNEL_GLOBAL_ALBEDO)
if globalmap == null:
globalmap = load(WHITE_TEXTURE_PATH)
_set_if_changed(_color_rect.material, "u_globalmap", globalmap)
# Need to check if it has changed, otherwise Godot's update spinner
# indicates that the editor keeps redrawing every frame,
# which is not intended and consumes more power.
static func _set_if_changed(sm: ShaderMaterial, param: String, v):
if sm.get_shader_parameter(param) != v:
sm.set_shader_parameter(param, v)
func _draw():
if _terrain == null:
return
if _mode == MODE_QUADTREE:
var lod_count := _terrain.get_lod_count()
if lod_count > 0:
# Fit drawing to rect
var qsize = 1 << (lod_count - 1)
var vsize := size
draw_set_transform(Vector2(0, 0), 0, Vector2(vsize.x / qsize, vsize.y / qsize))
_terrain._edit_debug_draw(self)
func _on_PopupMenu_id_pressed(id: int):
_set_mode(id)
|