gzoom のコピーする座標を動かせるようにしてみる

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

オフィシャル HSP でおかしな挙動をする具体例

オフィシャル HSP の表示結果
HSP on JS の表示結果

インフォメーション

公開日時
2008年11月21日 午後4時19分17秒
最終更新日時
2008年11月21日 午後5時4分8秒
カテゴリ
HSP