gzoom のコピー元、コピー先それぞれの座標とサイズを動かし動作を確かめられるスクリプトです。gsquare のコピーする四角形座標を動かせるようにしてみる の gzoom 版です。
作ったきっかけは HSP on JS GUI の試み で gzoom を実装するときにオフィシャル HSP での gzoom の動作を確かめていたら、反転コピーするときにコピーする範囲が画像の範囲を超えていたときの挙動がおかしいと気づいたことです。
#module
#deffunc boxline int x1, int y1, int x2, int y2
line x2, y1, x1, y1
line x2, y2
line x1, y2
line x1, y1
return
#deffunc boxline2 int x1, int y1, int x2, int y2
if x1 < x2 : min_x = x1 : max_x = x2 : else : min_x = x2 : max_x = x1
if y1 < y2 : min_y = y1 : max_y = y2 : else : min_y = y2 : max_y = y1
color 255, 255, 255
boxline min_x, min_y, max_x, max_y
color
boxline min_x - 1, min_y - 1, max_x + 1, max_y + 1
return
#deffunc bordered_line int x1, int y1, int x2, int y2
color
line x1 - 1, y1, x2 - 1, y2
line x1 + 1, y1, x2 + 1, y2
line x1, y1 - 1, x2, y2 - 1
line x1, y1 + 1, x2, y2 + 1
color 255, 255, 255
line x1, y1, x2, y2
return
#deffunc draw_box array rect, int x, int y
left = rect.0 : top = rect.1 : right = rect.2 : bottom = rect.3
if left < right : sign_x = 1 : else : sign_x = -1
if top < bottom : sign_y = 1 : else : sign_y = -1
bordered_line x + left, y + top, x + right, y + top
bordered_line x + right, y + top, x + right - 10 * sign_x, y + top - 5
bordered_line x + right, y + top, x + right - 10 * sign_x, y + top + 5
bordered_line x + left, y + top, x + left, y + bottom
bordered_line x + left, y + bottom, x + left - 5, y + bottom - 10 * sign_y
bordered_line x + left, y + bottom, x + left + 5, y + bottom - 10 * sign_y
bordered_line x + right, y + top, x + right, y + bottom
bordered_line x + left, y + bottom, x + right, y + bottom
color
circle x + left - 5, y + top - 5, x + left + 5, y + top + 5
color 255, 255, 255
circle x + left - 4, y + top - 4, x + left + 4, y + top + 4
return
#defcfunc between int val, int edge1, int edge2
if edge1 <= val and val <= edge2 : return 1
if edge2 <= val and val <= edge1 : return 1
return 0
#defcfunc circle_collision int ax, int ay, int bx, int by, int r
return r * r >= (ax - bx) * (ax - bx) + (ay - by) * (ay - by)
#global
screen_id_src = 1
src_w = 128 : src_h = 128
buffer screen_id_src, src_w, src_h
repeat 16
r = cnt * 255 / 15
y = cnt * 8
repeat 16
g = cnt * 255 / 15
x = cnt * 8
color r, g
boxf x, y, x + 7, y + 7
loop
loop
screen_id_dest = 2
dest_w = 320 : dest_h = 240
buffer screen_id_dest, dest_w, dest_h
box_w = 400
box_h = 400
margin_size = 16
box_src_x = margin_size
box_src_y = margin_size
box_dest_x = margin_size * 2 + box_w
box_dest_y = margin_size
offset_src_x = box_src_x + box_w / 2 - src_w / 2
offset_src_y = box_src_y + box_h / 2 - src_h / 2
offset_dest_x = box_dest_x + box_w / 2 - dest_w / 2
offset_dest_y = box_dest_y + box_h / 2 - dest_h / 2
src_rect = 5, 5, 100, 100
dup src_left, src_rect.0
dup src_top, src_rect.1
dup src_right, src_rect.2
dup src_bottom, src_rect.3
dest_rect = 20, 20, dest_w - 20, dest_h - 20
dup dest_left, dest_rect.0
dup dest_top, dest_rect.1
dup dest_right, dest_rect.2
dup dest_bottom, dest_rect.3
screen_id_main = 0
screen screen_id_main, box_w * 2 + margin_size * 3, box_h + margin_size * 2
dragging = 0 // ドラッグ中の辺 (+1: left, +2: top, +4: right, +8: bottom, 16: center, 17: right click, +0: src, +32: dest)
prev_key = 0
repeat
gosub *do_gzoom
gsel screen_id_main
stick key
left_clicking_trigger = key & 256
right_clicking_trigger = key & 512
stick key, 256 + 512
left_clicking = key & 256
right_clicking = key & 512
if left_clicking_trigger {
dragging = 0
repeat 2
if cnt : gosub *dup_from_dest : else : gosub *dup_from_src
gosub *collision_check_left
if dragging : dragging |= 32 * cnt : break
loop
} else : if right_clicking_trigger {
repeat 2
if cnt : gosub *dup_from_dest : else : gosub *dup_from_src
gosub *collision_check_right
if dragging : dragging |= 32 * cnt : break
loop
}
if dragging {
if left_clicking | right_clicking {
gosub *move
} else {
dragging = 0
}
}
redraw 0
color 255, 255, 255 : boxf
color 128, 128, 128
boxf box_src_x, box_src_y, box_src_x + box_w - 1, box_src_y + box_h - 1
boxf box_dest_x, box_dest_y, box_dest_x + box_w - 1, box_dest_y + box_h - 1
pos offset_src_x, offset_src_y
gcopy screen_id_src, 0, 0, src_w, src_h
pos offset_dest_x, offset_dest_y
gcopy screen_id_dest, 0, 0, dest_w, dest_h
draw_box src_rect, offset_src_x, offset_src_y
draw_box dest_rect, offset_dest_x, offset_dest_y
redraw
await 16
loop
stop
*collision_check_left
x = mousex - offset_x
y = mousey - offset_y
if circle_collision(x, y, left, top, 10) : dragging = 1+2 : return
if circle_collision(x, y, right, top, 10) : dragging = 4+2 : return
if circle_collision(x, y, right, bottom, 10) : dragging = 4+8 : return
if circle_collision(x, y, left, bottom, 10) : dragging = 1+8 : return
between_x = between(x, left, right)
between_y = between(y, top, bottom)
if between_y {
if abs(x - left) <= 8 : dragging = 1 : return
if abs(x - right) <= 8 : dragging = 4 : return
}
if between_x {
if abs(y - top) <= 8 : dragging = 2 : return
if abs(y - bottom) <= 8 : dragging = 8 : return
}
if between_x and between_y {
dragging = 16
drag_start_x = x
drag_start_y = y
dim drag_start_rect, 4
memcpy drag_start_rect, rect, 4 * 4
}
return
*collision_check_right
if between(mousex, box_x, box_x + box_w) and between(mousey, box_y, box_y + box_h) {
dragging = 17
left = mousex - offset_x
top = mousey - offset_y
right = mousex - offset_x
bottom = mousey - offset_y
}
return
*move
if dragging & 32 {
gosub *dup_from_dest
} else {
gosub *dup_from_src
}
d = dragging & 31
if d == 16 {
// 枠の中のクリック: サイズを変えずに枠全体を移動
if drag_start_rect.0 < drag_start_rect.2 {
dup start_min_x, drag_start_rect.0 : dup start_max_x, drag_start_rect.2
dup min_x, left : dup max_x, right
} else {
dup start_max_x, drag_start_rect.0 : dup start_min_x, drag_start_rect.2
dup max_x, left : dup min_x, right
}
if drag_start_rect.1 < drag_start_rect.3 {
dup start_min_y, drag_start_rect.1 : dup start_max_y, drag_start_rect.3
dup min_y, top : dup max_y, bottom
} else {
dup start_max_y, drag_start_rect.1 : dup start_min_y, drag_start_rect.3
dup max_y, top : dup min_y, bottom
}
x = start_min_x + mousex - drag_start_x
if x < box_x {
min_x = limit(x, box_x, box_x + box_w) - offset_x
max_x = min_x + (start_max_x - start_min_x)
} else {
max_x = limit(start_max_x + mousex - drag_start_x, box_x, box_x + box_w) - offset_x
min_x = max_x - (start_max_x - start_min_x)
}
y = start_min_y + mousey - drag_start_y
if y < box_y {
min_y = limit(y, box_y, box_y + box_h) - offset_y
max_y = min_y + (start_max_y - start_min_y)
} else {
max_y = limit(start_max_y + mousey - drag_start_y, box_y, box_y + box_h) - offset_y
min_y = max_y - (start_max_y - start_min_y)
}
return
}
if d == 17 {
// 右クリック
right = limit(mousex, box_x, box_x + box_w) - offset_x
bottom = limit(mousey, box_y, box_y + box_h) - offset_y
return
}
if d & 1 {
left = limit(mousex, box_x, box_x + box_w) - offset_x
} else : if d & 4 {
right = limit(mousex, box_x, box_x + box_w) - offset_x
}
if d & 2 {
top = limit(mousey, box_y, box_y + box_h) - offset_y
} else : if d & 8 {
bottom = limit(mousey, box_y, box_y + box_h) - offset_y
}
return
*dup_from_dest
dup rect, dest_rect
dup box_x, box_dest_x
dup box_y, box_dest_y
dup offset_x, offset_dest_x
dup offset_y, offset_dest_y
gosub *dup_rect
return
*dup_from_src
dup rect, src_rect
dup box_x, box_src_x
dup box_y, box_src_y
dup offset_x, offset_src_x
dup offset_y, offset_src_y
gosub *dup_rect
return
*dup_rect
dup left, rect.0
dup top, rect.1
dup right, rect.2
dup bottom, rect.3
return
*do_gzoom
gsel screen_id_dest
color 200, 200, 200 : boxf
pos dest_left, dest_top
gzoom dest_right - dest_left, dest_bottom - dest_top, screen_id_src, src_left, src_top, src_right - src_left, src_bottom - src_top
return

