gdharness 1.1.40 → 1.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -288,6 +288,10 @@ static func _areas_of(drawn: Array[Node]) -> Array[Rect2]:
|
|
|
288
288
|
## the click scrolls it into view first: what is drawn over its place now is not what it will land
|
|
289
289
|
## under. Judged not covered at all instead, a button below the fold of a roster that a full-screen
|
|
290
290
|
## page covered was picked over the ones in view, scrolled up under the page and pressed there.
|
|
291
|
+
## Whatever else the scroll holds moves with it and is judged where it goes. Judged where it sat, the
|
|
292
|
+
## card at the top of a tray scrolled down was drawn over a button above the view, because a later
|
|
293
|
+
## card is drawn over an earlier one, and a button below the view was passed by the same card only
|
|
294
|
+
## because the cards beside the bottom edge come before it.
|
|
291
295
|
##
|
|
292
296
|
## [param areas] holds the box around each of [param drawn], so everything whose box misses the
|
|
293
297
|
## point is passed over before anything costlier is asked of it. A window's box is in the space of
|
|
@@ -295,7 +299,8 @@ static func _areas_of(drawn: Array[Node]) -> Array[Rect2]:
|
|
|
295
299
|
## so a window is judged by [method _window_over] instead.
|
|
296
300
|
static func _cover_of(target: Control, drawn: Array[Node], areas: Array[Rect2]) -> Node:
|
|
297
301
|
var viewport: Viewport = target.get_viewport()
|
|
298
|
-
var
|
|
302
|
+
var moves: Dictionary[ScrollContainer, Vector2] = _scrolls_for(target)
|
|
303
|
+
var point: Vector2 = _centre_of(target) + _moved_by(target, moves)
|
|
299
304
|
var layer: int = _layer_of(target)
|
|
300
305
|
for at: int in drawn.size():
|
|
301
306
|
var other: Node = drawn[at]
|
|
@@ -304,9 +309,11 @@ static func _cover_of(target: Control, drawn: Array[Node], areas: Array[Rect2])
|
|
|
304
309
|
if _window_over(target, point, window):
|
|
305
310
|
return window
|
|
306
311
|
continue
|
|
307
|
-
if not areas[at].has_point(point):
|
|
308
|
-
continue
|
|
309
312
|
var control: Control = other
|
|
313
|
+
# The point where this control is now, which is where the scroll will carry it to the point.
|
|
314
|
+
var before: Vector2 = point - _moved_by(control, moves)
|
|
315
|
+
if not areas[at].has_point(before):
|
|
316
|
+
continue
|
|
310
317
|
if control == target or control.is_ancestor_of(target) or target.is_ancestor_of(control):
|
|
311
318
|
continue
|
|
312
319
|
if control.get_viewport() != viewport:
|
|
@@ -314,18 +321,34 @@ static func _cover_of(target: Control, drawn: Array[Node], areas: Array[Rect2])
|
|
|
314
321
|
var its_layer: int = _layer_of(control)
|
|
315
322
|
if its_layer < layer or (its_layer == layer and not control.is_greater_than(target)):
|
|
316
323
|
continue
|
|
317
|
-
if _holds(control,
|
|
324
|
+
if _holds(control, before) and not _clipped_away(control, point, moves):
|
|
318
325
|
return control
|
|
319
326
|
return null
|
|
320
327
|
|
|
321
328
|
|
|
322
|
-
##
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
+
## [param target]'s centre in its viewport, where it is now.
|
|
330
|
+
static func _centre_of(target: Control) -> Vector2:
|
|
331
|
+
return target.get_global_transform_with_canvas() * (target.size * 0.5)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
## How far the click moves what each ScrollContainer holding [param target] holds, to bring it into
|
|
335
|
+
## view: empty when no container clips it away, as nothing is scrolled then.
|
|
336
|
+
static func _scrolls_for(target: Control) -> Dictionary[ScrollContainer, Vector2]:
|
|
337
|
+
var none: Dictionary[ScrollContainer, Vector2] = {}
|
|
338
|
+
var centre: Vector2 = _centre_of(target)
|
|
339
|
+
if not _clipped_away(target, centre, none):
|
|
340
|
+
return none
|
|
341
|
+
return _where_it_lands(target, centre)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
## How far the scrolls in [param moves] carry [param node]: the sum over the containers holding it,
|
|
345
|
+
## and nothing for a container itself, which stays where it is while what it holds moves.
|
|
346
|
+
static func _moved_by(node: Node, moves: Dictionary[ScrollContainer, Vector2]) -> Vector2:
|
|
347
|
+
var moved: Vector2 = Vector2.ZERO
|
|
348
|
+
for holder: ScrollContainer in moves:
|
|
349
|
+
if holder.is_ancestor_of(node):
|
|
350
|
+
moved += moves[holder]
|
|
351
|
+
return moved
|
|
329
352
|
|
|
330
353
|
|
|
331
354
|
## Whether the embedded [param window] is drawn over [param point], [param target]'s centre in its
|
|
@@ -366,14 +389,15 @@ static func _holds(control: Control, point: Vector2) -> bool:
|
|
|
366
389
|
return Rect2(Vector2.ZERO, control.size).has_point(placed.affine_inverse() * point)
|
|
367
390
|
|
|
368
391
|
|
|
369
|
-
##
|
|
370
|
-
## view:
|
|
371
|
-
## first, which is how one brings a control into view. A target larger than a
|
|
372
|
-
## in it. Only a ScrollContainer, because that is all a click scrolls: another
|
|
373
|
-
## what it holds, a collapsed section for one, leaves the target where it is.
|
|
374
|
-
static func _where_it_lands(target: Control, point: Vector2) -> Vector2:
|
|
392
|
+
## How far each ScrollContainer holding [param target] moves what it holds once the click has
|
|
393
|
+
## scrolled [param target], centred at [param point], into view: as little as puts the whole of it
|
|
394
|
+
## inside each, innermost first, which is how one brings a control into view. A target larger than a
|
|
395
|
+
## container is centred in it. Only a ScrollContainer, because that is all a click scrolls: another
|
|
396
|
+
## container clipping what it holds, a collapsed section for one, leaves the target where it is.
|
|
397
|
+
static func _where_it_lands(target: Control, point: Vector2) -> Dictionary[ScrollContainer, Vector2]:
|
|
375
398
|
var drawn: Transform2D = target.get_global_transform_with_canvas()
|
|
376
399
|
var half: Vector2 = (drawn * Rect2(Vector2.ZERO, target.size)).size * 0.5
|
|
400
|
+
var moves: Dictionary[ScrollContainer, Vector2] = {}
|
|
377
401
|
var landed: Vector2 = point
|
|
378
402
|
var walk: Node = target.get_parent()
|
|
379
403
|
while walk != null and not (walk is Viewport):
|
|
@@ -382,12 +406,15 @@ static func _where_it_lands(target: Control, point: Vector2) -> Vector2:
|
|
|
382
406
|
var shown: Rect2 = holder.get_global_transform_with_canvas() * Rect2(Vector2.ZERO, holder.size)
|
|
383
407
|
var low: Vector2 = shown.position + half
|
|
384
408
|
var high: Vector2 = shown.end - half
|
|
385
|
-
|
|
409
|
+
var next: Vector2 = Vector2(
|
|
386
410
|
shown.get_center().x if low.x > high.x else clampf(landed.x, low.x, high.x),
|
|
387
411
|
shown.get_center().y if low.y > high.y else clampf(landed.y, low.y, high.y)
|
|
388
412
|
)
|
|
413
|
+
if next != landed:
|
|
414
|
+
moves[holder] = next - landed
|
|
415
|
+
landed = next
|
|
389
416
|
walk = walk.get_parent()
|
|
390
|
-
return
|
|
417
|
+
return moves
|
|
391
418
|
|
|
392
419
|
|
|
393
420
|
## Whether a click could not reach [param target] however it scrolled: its centre, where the click
|
|
@@ -395,8 +422,9 @@ static func _where_it_lands(target: Control, point: Vector2) -> Vector2:
|
|
|
395
422
|
## container the click does not scroll. A drawer parked off the side of the screen, or anything
|
|
396
423
|
## outside the 64 by 64 viewport of a game with no window, was listed among the controls on screen.
|
|
397
424
|
static func _off_screen(target: Control) -> bool:
|
|
398
|
-
var
|
|
399
|
-
|
|
425
|
+
var moves: Dictionary[ScrollContainer, Vector2] = _scrolls_for(target)
|
|
426
|
+
var point: Vector2 = _centre_of(target) + _moved_by(target, moves)
|
|
427
|
+
if _clipped_away(target, point, moves) or not target.get_viewport().get_visible_rect().has_point(point):
|
|
400
428
|
return true
|
|
401
429
|
var reached: Dictionary = Screen.reach(target.get_viewport(), point)
|
|
402
430
|
var viewport: Viewport = reached["viewport"]
|
|
@@ -404,16 +432,19 @@ static func _off_screen(target: Control) -> bool:
|
|
|
404
432
|
return not viewport.get_visible_rect().has_point(there)
|
|
405
433
|
|
|
406
434
|
|
|
407
|
-
## Whether a container clipping what it holds cuts [param point] off from [param control]
|
|
435
|
+
## Whether a container clipping what it holds cuts [param point] off from [param control], once the
|
|
436
|
+
## scrolls in [param moves] have carried each container wherever they carry it.
|
|
408
437
|
##
|
|
409
438
|
## Only up to the viewport [param control] is in. A dialog is a window, and the containers the game
|
|
410
439
|
## added it under are in another space: judged against a clipping one of those, every button of a
|
|
411
440
|
## confirmation was refused as off the screen while it sat in plain view.
|
|
412
|
-
static func _clipped_away(
|
|
441
|
+
static func _clipped_away(
|
|
442
|
+
control: Control, point: Vector2, moves: Dictionary[ScrollContainer, Vector2]
|
|
443
|
+
) -> bool:
|
|
413
444
|
var walk: Node = control.get_parent()
|
|
414
445
|
while walk != null and not (walk is Viewport):
|
|
415
446
|
var holder: Control = walk as Control
|
|
416
|
-
if holder != null and holder.clip_contents and not _holds(holder, point):
|
|
447
|
+
if holder != null and holder.clip_contents and not _holds(holder, point - _moved_by(holder, moves)):
|
|
417
448
|
return true
|
|
418
449
|
walk = walk.get_parent()
|
|
419
450
|
return false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.41",
|
|
4
4
|
"mcpName": "io.github.Aureliolo/gdharness",
|
|
5
5
|
"description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
|
|
6
6
|
"type": "module",
|