ClickableWindows - kyonides - 05-27-2024
ClickableWindows
HiddenChest Exclusive!
XP + VX + ACE Related
by Kyonides
Warning!
Other scripts of mine like PrintScene HC depend on this one.
These scriptlets allow you to click on the usual menu window options!
As long as you click on the area defined by the blinking cursor, you will be fine.
It does not fully support all windows but only child classes of Window_Selectable and a few others.
The Caveats
They are based on XP's and VX ACE's default scripts. There is no warranty they will work with custom ones.
Some scenes forced me to add calls like Input.double_left_click? or Input.right_click? to make them work properly.
Script Section
Script for the RMXP Editor
Code: # * ClickableWindow XP * #
# Scripter : Kyonides Arkanthes
# 2024-06-02
# This is a script demo that shows you how it is now possible to click once on
# a menu window to choose an option while ignoring the surrounding area.
# Normally, you would have to add some calls to Input.left_click? or
# Input.right_click? or even Input.middle_click? to your target scenes to make
# this work.
class Window_Selectable
def one_click_selection
# Set Index to invisible if clicked outside this window
self.index = -1
# Check each area - a list of Rect's
@area.size.times do |n|
next unless mouse_inside?(n)
self.index = n
break
end
end
def update
super
return unless self.active
return if @item == 0
# Added Left Click Check
if Input.left_click?
one_click_selection
return
end
if mouse_inside?
if Input.mouse_scroll_y?(:UP)
$game_system.se_play($data_system.cursor_se)
self.index = (@index - @column_max) % @item_max
return
elsif Input.mouse_scroll_y?(:DOWN)
$game_system.se_play($data_system.cursor_se)
self.index = (@index + @column_max) % @item_max
return
end
end
if Input.repeat?(Input::DOWN)
if (@column_max == 1 and Input.trigger?(Input::DOWN)) or
@index < @item_max - @column_max
$game_system.se_play($data_system.cursor_se)
@index = (@index + @column_max) % @item_max
end
end
if Input.repeat?(Input::UP)
if (@column_max == 1 and Input.trigger?(Input::UP)) or
@index >= @column_max
$game_system.se_play($data_system.cursor_se)
@index = (@index - @column_max + @item_max) % @item_max
end
end
if Input.repeat?(Input::RIGHT)
if @column_max >= 2 and @index < @item_max - 1
$game_system.se_play($data_system.cursor_se)
@index += 1
end
end
if Input.repeat?(Input::LEFT)
if @column_max >= 2 and @index > 0
$game_system.se_play($data_system.cursor_se)
@index -= 1
end
end
if Input.repeat?(Input::R)
if self.top_row + (self.page_row_max - 1) < (self.row_max - 1)
$game_system.se_play($data_system.cursor_se)
@index = [@index + self.page_item_max, @item_max - 1].min
self.top_row += self.page_row_max
end
end
if Input.repeat?(Input::L)
if self.top_row > 0
$game_system.se_play($data_system.cursor_se)
@index = [@index - self.page_item_max, 0].max
self.top_row -= self.page_row_max
end
end
if self.active and @help_window != nil
update_help if @index >= 0
end
update_cursor_rect
end
def get_area_rect(n)
rw = self.width / @column_max - 32
rx = 8 + n % @column_max * (rw + 32)
ry = n / @column_max * 32 - self.oy
Rect.new(rx, ry, rw, 32)
end
end
class Window_Command
def draw_item(n, color)
@area[n] ||= get_area_rect(n)
c = self.contents
c.font.color = color
rect = Rect.new(4, 32 * n, c.width - 8, 32)
c.fill_rect(rect, Color.new(0, 0, 0, 0))
c.draw_text(rect, @commands[n])
end
end
class Window_MenuStatus
def refresh
self.contents.clear
@item_max = $game_party.actors.size
for i in 0...$game_party.actors.size
x = 64
y = i * 116
@area[i] ||= Rect.new(0, i * 116, self.width - 32, 96)
actor = $game_party.actors[i]
draw_actor_graphic(actor, x - 40, y + 80)
draw_actor_name(actor, x, y)
draw_actor_class(actor, x + 144, y)
draw_actor_level(actor, x, y + 32)
draw_actor_state(actor, x + 90, y + 32)
draw_actor_exp(actor, x, y + 64)
draw_actor_hp(actor, x + 236, y + 32)
draw_actor_sp(actor, x + 236, y + 64)
end
end
end
class Window_Target
def refresh
self.contents.clear
for i in 0...$game_party.actors.size
x = 4
y = i * 116
@area[i] ||= Rect.new(0, i * 116, self.width - 32, 96)
actor = $game_party.actors[i]
draw_actor_name(actor, x, y)
draw_actor_class(actor, x + 144, y)
draw_actor_level(actor, x + 8, y + 32)
draw_actor_state(actor, x + 8, y + 64)
draw_actor_hp(actor, x + 152, y + 32)
draw_actor_sp(actor, x + 152, y + 64)
end
end
end
class Window_EquipRight
def initialize(actor)
super(272, 64, 368, 192)
@click_width = width - 32
self.contents = Bitmap.new(@click_width, height - 32)
@actor = actor
create_areas
refresh
self.index = 0
end
def create_areas
5.times {|n| @area << Rect.new(4, 32 * n, @click_width, 32) }
end
end
class Window_SaveFile
alias :kyon_click_win_win_svfl_init :initialize
def initialize(file_index, filename)
kyon_click_win_win_svfl_init(file_index, filename)
@area << self.contents.rect
end
end
class Window_Message
alias :kyon_click_win_win_mess_init :initialize
def initialize
kyon_click_win_win_mess_init
self.pause_x = self.width - 80
end
end
class Scene_Title
alias :kyon_click_win_scn_ttl_main :main
def start
@title = Sprite.new
@title.set_xyz(0, 60, 100)
@title.bitmap = b = Bitmap.new(Graphics.width, 60)
font = b.font
font.size = 52
font.outline = true
font.outline_size = 4
b.draw_text(b.rect, Game::TITLE, 1)
@day_index = 0
@days = %w{Sunday Monday Tuesday Wednesday Thursday Friday Saturday}
# Make day of the week graphic
@block = Sprite.new
@block.set_xyz(12, Graphics.height - 40, 100)
@bitmap = Bitmap.new(200, 36)
font = @bitmap.font
font.size = 32
font.outline = true
font.outline_size = 2
@bitmap.draw_text(@bitmap.rect, @days[@day_index], 1)
@block.bitmap = @bitmap
end
def terminate
@bitmap.dispose
@block.dispose
@title.bitmap.dispose
@title.dispose
end
def main
start unless $BTEST
kyon_click_win_scn_ttl_main
terminate unless $BTEST
end
def update
@command_window.update
# Added Right Click Check
if Input.right_click?
$game_system.se_play($data_system.cursor_se)
if @command_window.index < 2
@command_window.index = 2
Audio.bgm_pause
else
@command_window.index = -1
Audio.bgm_resume
end
# Added Left Click Check
elsif Input.trigger?(Input::C) or Input.double_left_click?
case @command_window.index
when 0 # New game
Graphics.center_window
command_new_game
when 1 # Continue
Graphics.center_window
command_continue
when 2 # Shutdown
command_shutdown
end
elsif Input.repeat?(Input::KeyD) or Input.repeat_right_click?
$game_system.se_play($data_system.cursor_se)
@day_index = (@day_index + 1) % 7
@bitmap.clear
@bitmap.draw_text(@bitmap.rect, @days[@day_index], 1)
end
end
end
class Scene_Map
def update
loop do
$game_map.update
$game_system.map_interpreter.update
$game_player.update
$game_system.update
$game_screen.update
break unless $game_temp.player_transferring
transfer_player
break if $game_temp.transition_processing
end
@spriteset.update
@message_window.update
if $game_temp.gameover
$scene = Scene_Gameover.new
return
end
if $game_temp.to_title
$scene = Scene_Title.new
return
end
if $game_temp.transition_processing
$game_temp.transition_processing = false
if $game_temp.transition_name == ""
Graphics.transition(20)
else
Graphics.transition(40, "Graphics/Transitions/" +
$game_temp.transition_name)
end
end
if Input.trigger?(Input::KeyP)
$game_system.se_play($data_system.shop_se)
Graphics.screenshot
return
end
return if $game_temp.message_window_showing
if $game_player.encounter_count == 0 and $game_map.encounter_list != []
unless $game_system.map_interpreter.running? or
$game_system.encounter_disabled
n = rand($game_map.encounter_list.size)
troop_id = $game_map.encounter_list[n]
if $data_troops[troop_id] != nil
$game_temp.battle_calling = true
$game_temp.battle_troop_id = troop_id
$game_temp.battle_can_escape = true
$game_temp.battle_can_lose = false
$game_temp.battle_proc = nil
end
end
end
# Added Right Click Check
if Input.trigger?(Input::B) or Input.double_right_click?
unless $game_system.map_interpreter.running? or
$game_system.menu_disabled
$game_temp.menu_calling = true
$game_temp.menu_beep = true
end
end
if $DEBUG and Input.press?(Input::F9)
$game_temp.debug_calling = true
end
unless $game_player.moving?
if $game_temp.battle_calling
call_battle
elsif $game_temp.shop_calling
call_shop
elsif $game_temp.name_calling
call_name
elsif $game_temp.menu_calling
call_menu
elsif $game_temp.save_calling
call_save
elsif $game_temp.debug_calling
call_debug
end
end
end
end
class Scene_Menu
def main
start
Graphics.transition
loop do
Graphics.update
Input.update
update
if $scene != self
break
end
end
Graphics.freeze
terminate
end
def start
create_command_window
create_windows
Input.mouse_set_xy(80, 28 + @menu_index * 32)
end
def create_command_window
s1 = $data_system.words.item
s2 = $data_system.words.skill
s3 = $data_system.words.equip
s4 = "Status"
s5 = "Save"
s6 = "End Game"
@command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6])
@command_window.index = @menu_index
if $game_party.actors.size == 0
@command_window.disable_item(0)
@command_window.disable_item(1)
@command_window.disable_item(2)
@command_window.disable_item(3)
end
if $game_system.save_disabled
@command_window.disable_item(4)
end
end
def create_windows
@playtime_window = Window_PlayTime.new
@playtime_window.x = 0
@playtime_window.y = 224
@steps_window = Window_Steps.new
@steps_window.x = 0
@steps_window.y = 320
@gold_window = Window_Gold.new
@gold_window.x = 0
@gold_window.y = 416
@status_window = Window_MenuStatus.new
@status_window.x = 160
@status_window.y = 0
end
def terminate
@command_window.dispose
@playtime_window.dispose
@steps_window.dispose
@gold_window.dispose
@status_window.dispose
end
def update_command
# Added Right Click Check
if Input.trigger?(Input::B) or Input.double_right_click?
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return
end
# Added Left Click Check
if Input.trigger?(Input::C) or Input.double_left_click?
if $game_party.actors.size == 0 and @command_window.index < 4
$game_system.se_play($data_system.buzzer_se)
return
end
case @command_window.index
when 0 # item
$game_system.se_play($data_system.decision_se)
$scene = Scene_Item.new
when 1 # skill
$game_system.se_play($data_system.decision_se)
@command_window.active = false
@status_window.active = true
@status_window.index = 0
Input.mouse_set_xy(@command_window.width + 120, 28)
when 2 # equipment
$game_system.se_play($data_system.decision_se)
@command_window.active = false
@status_window.active = true
@status_window.index = 0
Input.mouse_set_xy(@command_window.width + 120, 28)
when 3 # status
$game_system.se_play($data_system.decision_se)
@command_window.active = false
@status_window.active = true
@status_window.index = 0
Input.mouse_set_xy(@command_window.width + 120, 28)
when 4 # save
if $game_system.save_disabled
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.decision_se)
$scene = Scene_Save.new
when 5 # end game
$game_system.se_play($data_system.decision_se)
$scene = Scene_End.new
end
return
end
end
def update_status
# Added Double Right Click Check
if Input.trigger?(Input::B) or Input.double_right_click?
$game_system.se_play($data_system.cancel_se)
@command_window.active = true
@status_window.active = false
@status_window.index = -1
Input.mouse_set_xy(80, 28 + @command_window.index * 32)
return
end
# Modified OK Button Functionality
if Input.trigger?(Input::C)
process_status
return
# Added Double Left Click Check
elsif Input.double_left_click?
return unless @status_window.mouse_inside?(@status_window.index)
process_status
end
end
def process_status
case @command_window.index
when 1 # skill
if $game_party.actors[@status_window.index].restriction >= 2
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.decision_se)
$scene = Scene_Skill.new(@status_window.index)
when 2 # equipment
$game_system.se_play($data_system.decision_se)
$scene = Scene_Equip.new(@status_window.index)
when 3 # status
$game_system.se_play($data_system.decision_se)
$scene = Scene_Status.new(@status_window.index)
end
end
end
class Scene_Item
alias :kyon_click_win_scn_item_up_item :update_item
def update_item
kyon_click_win_scn_item_up_item
# Added Double Right Click Check
if Input.double_right_click?
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Menu.new(0)
return
end
end
end
class Scene_Equip
alias :kyon_click_win_scn_equip_up_right :update_right
def update_right
kyon_click_win_scn_equip_up_right
if Input.double_right_click?
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Menu.new(2)
return
elsif Input.double_left_click?
n = @right_window.index
if !@right_window.mouse_inside?(n) or @actor.equip_fix?(n)
$game_system.se_play($data_system.buzzer_se)
return
end
$game_system.se_play($data_system.decision_se)
@right_window.active = false
@item_window.active = true
@item_window.index = 0
return
end
end
end
class Scene_File
alias :kyon_click_win_scn_fl_up :update
def update
kyon_click_win_scn_fl_up
if Input.double_right_click?
on_cancel
return
elsif Input.double_left_click?
@savefile_windows.each_with_index do |win, n|
next unless win.mouse_inside?(0)
choose_file(n)
on_decision(make_filename(n))
$game_temp.last_file_index = n
break
end
return
elsif Input.left_click?
@savefile_windows.each_with_index do |win, n|
next unless win.mouse_inside?(0)
choose_file(n)
break
end
return
end
end
def choose_file(n)
@savefile_windows[@file_index].selected = false
@savefile_windows[n].selected = true
@file_index = n
end
end
class Scene_End
def update
@command_window.update
# Added Right Click Check
if Input.trigger?(Input::B) or Input.double_right_click?
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Menu.new(5)
return
# Added Left Click Check
elsif Input.trigger?(Input::C) or Input.double_left_click?
case @command_window.index
when 0 # to title
command_to_title
when 1 # shutdown
command_shutdown
when 2 # quit
command_cancel
end
return
end
end
end
Script for RM VX Editor
Code: # * ClickableWindow VX * #
# Scripter : Kyonides Arkanthes
# 2024-06-01
# This is a script demo that shows you how it is now possible to click once on
# a menu window to choose an option while ignoring the surrounding area.
# Normally, you would have to add some calls to Input.left_click? or
# Input.right_click? or even Input.middle_click? to your target scenes to make
# this work.
class Window_Selectable
def one_click_selection
# Set Index to invisible if clicked outside this window
self.index = -1
# Check each area - a list of Rect's
@area.size.times do |n|
next unless mouse_inside?(n)
self.index = n
Sound.play_cursor
break
end
end
def cursor_movable?
return false if !visible or !active
return false if @item_max == 0 or @opening or @closing
return true
end
def update
super
if cursor_movable?
last_index = @index
# Added Left Click Check
if Input.left_click?
one_click_selection
return
end
if mouse_inside?
if Input.mouse_scroll_y?(:UP)
Sound.play_cursor
self.index = (@index - @column_max) % @item_max
return
elsif Input.mouse_scroll_y?(:DOWN)
Sound.play_cursor
self.index = (@index + @column_max) % @item_max
return
end
end
if Input.repeat?(Input::DOWN)
cursor_down(Input.trigger?(Input::DOWN))
end
if Input.repeat?(Input::UP)
cursor_up(Input.trigger?(Input::UP))
end
if Input.repeat?(Input::RIGHT)
cursor_right(Input.trigger?(Input::RIGHT))
end
if Input.repeat?(Input::LEFT)
cursor_left(Input.trigger?(Input::LEFT))
end
if Input.repeat?(Input::R)
cursor_pagedown
end
if Input.repeat?(Input::L)
cursor_pageup
end
if @index != last_index
Sound.play_cursor
end
end
update_cursor
call_update_help
end
end
class Window_Command
def draw_item(n, enabled = true)
rect = @area[n] ||= item_rect(n)
rect.x += 4
rect.width -= 8
self.contents.clear_rect(rect)
self.contents.font.color = normal_color
self.contents.font.color.alpha = enabled ? 255 : 128
self.contents.draw_text(rect, @commands[n])
end
end
class Scene_Title
def update
super
@command_window.update
# Added Left Click Check
if Input.trigger?(Input::C) or Input.double_left_click?
case @command_window.index
when 0 #New game
command_new_game
when 1 # Continue
command_continue
when 2 # Shutdown
command_shutdown
end
# Added Right Click Check
elsif Input.right_click?
$game_system.se_play($data_system.cursor_se)
if @command_window.index < 2
@command_window.index = 2
end
end
end
end
class Scene_Menu
def update_command_selection
if Input.trigger?(Input::B) or Input.double_right_click?
Sound.play_cancel
$scene = Scene_Map.new
elsif Input.trigger?(Input::C) or Input.double_left_click?
if $game_party.members.size == 0 and @command_window.index < 4
Sound.play_buzzer
return
elsif $game_system.save_disabled and @command_window.index == 4
Sound.play_buzzer
return
end
Sound.play_decision
case @command_window.index
when 0 # Item
$scene = Scene_Item.new
when 1,2,3 # Skill, equipment, status
start_actor_selection
when 4 # Save
$scene = Scene_File.new(true, false, false)
when 5 # End Game
$scene = Scene_End.new
end
end
end
end
class Scene_End
def update
super
update_menu_background
@command_window.update
if Input.trigger?(Input::B) or Input.double_right_click?
Sound.play_cancel
return_scene
elsif Input.trigger?(Input::C) or Input.double_left_click?
case @command_window.index
when 0 # to title
command_to_title
when 1 # shutdown
command_shutdown
when 2 # quit
command_cancel
end
end
end
end
Script for RM VX ACE Editor
Code: # * ClickableWindow ACE * #
# Scripter : Kyonides Arkanthes
# 2024-06-02
# This is a script demo that shows you how it is now possible to click once on
# a menu window to choose an option while ignoring the surrounding area.
# Normally, you would have to add some calls to Input.left_click? or
# Input.right_click? or even Input.middle_click? to your target scenes to make
# this work.
class Window_Selectable
def process_cursor_move
return unless cursor_movable?
last_index = @index
if Input.left_click?
# Set Index to invisible if clicked outside this window
self.index = -1
# Check each area - a list of Rect's
@area.size.times do |n|
next unless mouse_inside?(n)
self.index = n
Sound.play_cursor
break
end
return
end
cursor_down (Input.trigger?(:DOWN)) if Input.repeat?(:DOWN)
cursor_up (Input.trigger?(:UP)) if Input.repeat?(:UP)
cursor_right(Input.trigger?(:RIGHT)) if Input.repeat?(:RIGHT)
cursor_left (Input.trigger?(:LEFT)) if Input.repeat?(:LEFT)
cursor_pagedown if !handle?(:pagedown) && Input.trigger?(:R)
cursor_pageup if !handle?(:pageup) && Input.trigger?(:L)
Sound.play_cursor if @index != last_index
end
def process_handling
return unless open? && active
return process_ok if ok_enabled? && Input.double_left_click?
return process_cancel if cancel_enabled? && Input.double_right_click?
return process_ok if ok_enabled? && Input.trigger?(:C)
return process_cancel if cancel_enabled? && Input.trigger?(:B)
return process_pagedown if handle?(:pagedown) && Input.trigger?(:R)
return process_pageup if handle?(:pageup) && Input.trigger?(:L)
end
end
class Window_Command
def draw_item(n)
rect = @area[n] ||= item_rect_for_text(n)
change_color(normal_color, command_enabled?(n))
draw_text(rect, command_name(n), alignment)
end
end
class Window_MenuCommand
def select_last
select_symbol(@@last_command_symbol)
Input.mouse_set_xy(80, 20 + @index * 24)
end
end
class Window_SaveFile
alias :kyon_click_win_win_svfl_init :initialize
def initialize(height, index)
kyon_click_win_win_svfl_init(height, index)
@area << self.contents.rect
end
end
class Scene_File
def update_savefile_selection
if Input.double_left_click?
@savefile_windows.each_with_index do |win, n|
next unless win.mouse_inside?
choose_file(n)
on_savefile_ok
break
end
return
elsif Input.left_click?
@savefile_windows.each_with_index do |win, n|
next unless win.mouse_inside?
choose_file(n)
break
end
return
elsif Input.double_right_click?
on_savefile_cancel
return
end
return on_savefile_ok if Input.trigger?(:C)
return on_savefile_cancel if Input.trigger?(:B)
update_cursor
end
def choose_file(n)
@savefile_windows[@index].selected = false
@savefile_windows[n].selected = true
@index = n
ensure_cursor_visible
end
end
Terms & Conditions
Free for any kind of game running on the HiddenChest engine.
Due credit is mandatory.
Don't post the contents of this topic anywhere else!
You better paste a link to this thread and make them come here instead.
That's it!
RE: ClickableWindows - kyonides - 06-03-2024
Small Update + New Script
Well, basides crafting the VX edition of my script, I've also taking advantage of Window#mouse_inside? without any arguments to let the whole window recognize the current position of your beloved mouse pointer. It also lets you place the cursor right on top of the selected option as well via Input.mouse_set_xy(x, y). Just be aware of the fact that it might rush to that point even before the scene has changed. So you gotta choose the most strategic chunk of code for your mouse to make that long jump, avoiding that strange event from ever taking place.
|