+- Save-Point (https://www.save-point.org)
+-- Forum: Material Development (https://www.save-point.org/forum-8.html)
+--- Forum: Scripts Database (https://www.save-point.org/forum-39.html)
+---- Forum: RPGMaker XP (RGSS) Engine (https://www.save-point.org/forum-116.html)
+---- Thread: Windowskin Selection Menu (/thread-8954.html)
Windowskin Selection Menu - DerVVulfman - 05-23-2024
Windowskin Selection Menu Version: 1.2
Introduction
This menu addition allows the player to select a windowskin for use in their menus. It overwrites the $game_system.windowskin_name value that is initially set on game start, and is normally saved within savegames.
Features
Double-line help window class
All text set in the config
Skins can be unlocked
Text alignment in menu
Skin Validity testing
Return to menu or to the map
Menu return index control
Script
Select It Here
Code:
#==============================================================================
# ** Windowskin Seletion Menu
#------------------------------------------------------------------------------
# by DerVVulfman
# version 1.2
# 05-22-2024 (MM/DD/YYYY)
# RGSS / RMXP
#------------------------------------------------------------------------------
#
# INTRODUCTION:
# =============
#
# This menu addition allows the player to select a windowskin for use in
# their menus. It overwrites the $game_system.windowskin_name value that
# is initially set on game start, and is normally saved within savegames.
#
# Features include:
# * Double-line help window class - May offer more information than before
# * All text set in the config - For non-English or multi-lang support
# * Skins can be unlocked - Allow the player to gain more skins
# * Text alignment in menu - Your choice on skin title justification
# * Skin Validity testing - Will not load a skin if not present
# * Return to menu or to the map - It returns to the map, but can go to menu
# * Menu return index control - Allows you to set the main menu cursor
#
#
#------------------------------------------------------------------------------
#
# SCRIPT CALLS:
# =============
#
# To use within the main menu:
# ----------------------------
# USE: $scene = Scene_SkinSelect.new(true)
# - - - - - - - - - - - - - - - - - - - - - - -
# The 'true' boolean within the argument informs the system that it is
# to return to the main menu. See line 472 if you need to exit to ano-
# ther menu other than Scene_Menu itself.
#
# To use within the field map:
# ----------------------------
# USE: $scene = Scene_SkinSelect.new()
# -or-
# skin_selector
# - - - - - - - - - - - - - - - - - - - - - - -
# This time, the 'true' boolean is not being put to use when evoking
# the Scene_SkinSelect command. This tells the system that it will be
# returning to the field map.
# The 'skin_selector' command is merely a more convenient call.
#
# To lock or unlock a windowskin:
# -------------------------------
# USE: skin_lock(skin_id)
# -or-
# skin_unlock(skin_id)
# * (skin_id = the ID key for the windowskin(s) so configured)
# - - - - - - - - - - - - - - - - - - - - - - -
# Rather than edit the $game_system.unlocked_skins array manually, the
# two commands here allow you to remove a skin from the menu,or to add
# one when you wish. You can only add one per call, but can make cu-
# lative calls:
# Ex: @>Text: Performing locks and unlocks
# @>Script: skin_unlock(4)
# @>Script: skin_unlock(5)
# @>Script: skin_lock(3)
#
#
#------------------------------------------------------------------------------
#
# AVAILABLE CLASSES AND COMMANDS:
# ===============================
#
#
# * Window_2LayerHelp
# -----------------
# Based upon and inheriting methods from Window_Help, this class is designed
# to render a help window that has two individual lines of text. Each of the
# lines are set by its own variation of the 'set_text' method.
#
# * RPG::CACHE Test Type 1
# ----------------------
# Test Type 1 is a method which tests for the existence of a defined graphics
# file within any of the Graphcs\Cacheable folders. But, Test Type 1 is only
# functional for Cacheable graphics that have no 'hue' setting. That would be
# Test Type 2 (used in some of my other works).
#
# For this script's purpose, it ensures that you do not accidentally attempt
# to select a windowskin that does not exist.
#
#
#------------------------------------------------------------------------------
#
# INSTALLATION:
#
# It is recommended to be placed above Main and below Scene_Debug within your
# project. If intended to be used within a menu script, it is the end-user's
# responsibility for insertion.
#
#
#------------------------------------------------------------------------------
#
# COMPATABILITY:
#
# Designed for use with RPGMaker XP, and only performs one single alias com-
# mand for Game_System. All other classes and modules are custom. It cannot
# account for scripts that alter the use of windowskins in menus, messagees,
# or the like.
#
#
#==============================================================================
#
# TERMS AND CONDITIONS:
#
# Free for use, even within commercial products. Only due credit is required.
#
#
#==============================================================================
module SkinSelect
# --------------------------------------------------------------------------
LIST = {} # Do Not Touch
# --------------------------------------------------------------------------
# LIST OF WINDOWSKINS TO SHOW IN THE MENU
# ---------------------------------------
#
# ID Skin's name in the menu Filename in the Windowskin folder
#====== ======================== =================================
LIST[0] = [ "Blue (Default)", "001-Blue01"]
LIST[1] = [ "Marble", "Sk3in1-1"]
LIST[2] = [ "Pink Marble", "Skin1-2"]
# Skins unlocked at start
UNLOCKED = [0,1,11,12,13,14]
# SKIN DISPLAY WINDOW DEFINITIONS
# -------------------------------
#
# Lines of text appearing in custom help window
TEXT1 = "Changes the windowskin used in the menus."
TEXT2 = "(This will not change the windowskin of speech balloons.)"
#
LIST_RECT = [320, 96, 320, 352] # Window dimensions including coords
COLUMNS = 1 # Columns to show in the window
ALIGN = 1 # Alignment of skin names in window
# 0=left, 1=center, 2=right
# Index position when returning to Main Menu
MENU_INDEX = 0
end
#==============================================================================
# ** RPG::Cache
#------------------------------------------------------------------------------
# This is a module that loads each of RPGXP's graphic formats, creates a
# Bitmap object, and retains it.
#==============================================================================
module RPG::Cache
#--------------------------------------------------------------------------
# * Test Cache File #1 (no hue option)
# type : cache type (autotile, icon, picture, etc.)
# filename : filename of the cached bitmap
#--------------------------------------------------------------------------
def self.test_1(type, filename)
failed = false
begin
bitmap = eval("self.#{type}(filename)")
rescue Errno::ENOENT
failed = true
end
return !failed
end
end
#==============================================================================
# ** Game_System
#------------------------------------------------------------------------------
# This class handles data surrounding the system. Backround music, etc.
# is managed here as well. Refer to "$game_system" for the instance of
# this class.
#==============================================================================
class Game_System
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :unlocked_skins # magic number
#--------------------------------------------------------------------------
# * Alias Listings
#--------------------------------------------------------------------------
alias game_system_windowskin_menu_initialize initialize
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
# Perform the original call
game_system_windowskin_menu_initialize
# Define the unlocked_skins array
@unlocked_skins = SkinSelect::UNLOCKED
end
end
#==============================================================================
# ** Window_2LayerHelp
#------------------------------------------------------------------------------
# This window shows two layers of help explanations passed into it. It inhe-
# rits from the base Window_Help class.
#==============================================================================
class Window_2LayerHelp < Window_Help
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super()
self.height = height = 96
self.contents = Bitmap.new(width - 32, height - 32)
end
#--------------------------------------------------------------------------
# * Set Skin Text
# text1 : 1st text string displayed in window
# text2 : 2nd text string displayed in window
# align : alignment (0..flush left, 1..center, 2..flush right)
#--------------------------------------------------------------------------
def set_text(text1, text2, align = 0)
# If at least one part of text and alignment differ from last time
if text1 != @text1 or text2 != @text2 or align != @align
# Redraw text
self.contents.clear
self.contents.font.color = normal_color
self.contents.draw_text(4, 0, self.width - 40, 32, text1, align)
self.contents.draw_text(4, 32, self.width - 40, 32, text2, align)
@text1 = text1
@text2 = text2
@actor = nil
end
self.visible = true
end
end
#==============================================================================
# ** Window_SkinSelect
#------------------------------------------------------------------------------
# This window displays skins available in the windowskin selection screen
#==============================================================================
class Window_SkinSelect < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
x = SkinSelect::LIST_RECT[0]
y = SkinSelect::LIST_RECT[1]
w = SkinSelect::LIST_RECT[2]
h = SkinSelect::LIST_RECT[3]
super(x, y, w, h)
@column_max = SkinSelect::COLUMNS
refresh
self.index = 0
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
# Clear window contents
if self.contents != nil
self.contents.dispose
self.contents = nil
end
#
# Create temporary data array
@data = []
# Get Keys for all configured skins
keys = SkinSelect::LIST.keys
keys.sort!
#
# Cycle through all keys
for key in keys
# Skip if skin not unlocked
next if !$game_system.unlocked_skins.include?(key)
# Push skin into temporary data array
@data.push(SkinSelect::LIST[key])
end
#
# Exit if item count is 0 or less (less is impossible, but...)
@item_max = @data.size
return unless @item_max > 0
#
# Draw contents for all items
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_skin(i)
end
end
#--------------------------------------------------------------------------
# * Get windowskin filename
#--------------------------------------------------------------------------
def skin
return @data[self.index][1]
end
#--------------------------------------------------------------------------
# * Draw Item
# index : item number
#--------------------------------------------------------------------------
def draw_skin(index)
txt = @data[index][0] # Get windowskin name
w = (self.width) / @column_max # Define text width
x = index % @column_max * w # Set X coordinates
y = index / @column_max * 32 # Set Y coordinates
a = SkinSelect::ALIGN # Set the alignment
rect = Rect.new(x, y, w, 32) # Define text area
rect_color = Color.new(0, 0, 0, 0) # Set color to clear text
self.contents.fill_rect(rect, rect_color) # Clear the area for text
self.contents.draw_text(x+4, y, w-40, 32, txt, a) # Draw the text
end
end
#==============================================================================
# ** Interpreter
#------------------------------------------------------------------------------
# This interpreter runs event commands. This class is used within the
# Game_System class and the Game_Event class.
#==============================================================================
class Interpreter
#--------------------------------------------------------------------------
# * Execute skin selector menu
#--------------------------------------------------------------------------
def skin_selector
$scene = Scene_SkinSelect.new()
end
#--------------------------------------------------------------------------
# * Unlock a windowskin
# skin_id : ID / Key to a skin
#--------------------------------------------------------------------------
def skin_unlock(skin_id)
# exit if already unlocked
return if $game_system.unlocked_skins.include?(skin_id)
# Add the skin_id / key to the unlocked skin array
$game_system.unlocked_skins.push(skin_id)
end
#--------------------------------------------------------------------------
# * Lock a windowskin
# skin_id : ID / Key to a skin
#--------------------------------------------------------------------------
def skin_lock(skin_id)
# Exit if already locked
return if !$game_system.unlocked_skins.include?(skin_id)
# Delete skin_id / key from the unlocked skin array
$game_system.unlocked_skins.delete(skin_id)
end
end
#==============================================================================
# ** Scene_SkinSelect
#------------------------------------------------------------------------------
# This class performs windowskin selection processing.
#==============================================================================
class Scene_SkinSelect
#--------------------------------------------------------------------------
# * Object Initialization
# to_menu : whether the scene exits to the menu (to the map by default)
#--------------------------------------------------------------------------
def initialize(to_menu=false)
@to_menu = to_menu
end
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
main_windows # Make help window, skin window
Graphics.transition # Execute transition
loop do # Main loop
break unless main_loop? # Abort loop if not in current scene
end
Graphics.freeze # Prepare for transition
main_dispose # Dispose of windows
end
#--------------------------------------------------------------------------
# * Main Processing (when creating windows for scene)
#--------------------------------------------------------------------------
def main_windows
@help_window = Window_2LayerHelp.new # Make the 2-line help window
@skin_window = Window_SkinSelect.new # Make the skin select window
text1 = SkinSelect::TEXT1 # Get 1st line of help text
text2 = SkinSelect::TEXT2 # Get 2nd line of help text
@help_window.set_text(text1, text2) # Apply text to the help window
end
#--------------------------------------------------------------------------
# * Main Processing (when performing scene activity)
#--------------------------------------------------------------------------
def main_loop?
Graphics.update # Update game screen
Input.update # Update input information
update # Frame update
return true if $scene == self # Exit method true if scene unchanged
return false # Exit method false as scene changed
end
#--------------------------------------------------------------------------
# * Main Processing (when removing scene-specific values)
#--------------------------------------------------------------------------
def main_dispose
@help_window.dispose # Dispose of help window
@skin_window.dispose # Dispose of skin select window
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
@skin_window.update # Update the skin select window
return if update_cancel? # Exit if cancelled/exiting
return if update_decision? # Exit on decision made
end
#--------------------------------------------------------------------------
# * Frame Update (when cancelling selection)
#--------------------------------------------------------------------------
def update_cancel?
# Exit method with false unless Cancel trigger
return false unless Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Perform exit
update_exit
# Exit method
return true
end
#--------------------------------------------------------------------------
# * Frame Update (when making windowskin selection)
#--------------------------------------------------------------------------
def update_decision?
# Exit method with false unless Select trigger
return false unless Input.trigger?(Input::C)
# Get currently selected data on the item window
index = @skin_window.skin
# Test for a valid windowskin in the Graphics\Windowskin folder
returned = RPG::Cache.test_1('windowskin', index)
# if a valid windowskin exists
if returned
# Set and save in the game_system class
$game_system.windowskin_name = index
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Perform exit
update_exit
# Exit method
return true
end
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
# Exit method
return false
end
#--------------------------------------------------------------------------
# * Frame Update (when exiting the Skin Select menu)
#--------------------------------------------------------------------------
def update_exit
# If exit returns to the menu
if @to_menu
# Switch to menu screen
$scene = Scene_Menu.new(SkinSelect::MENU_INDEX)
return
end
# Switch to map screen
$scene = Scene_Map.new
end
end
Instructions
It is recommended to be placed above Main and below Scene_Debug within your project. If intended to be used within a menu script, it is the end-user's responsibility for insertion.
Additional instructions on installation and the available script calls are in the script itself.
Compatibility
Designed for use with RPGMaker XP, and only performs one single alias command for Game_System. All other classes and modules are custom. It cannot account for scripts that alter the use of windowskins in menus, messages, or the like.
Terms and Conditions
Free for use, even within commercial products. Only due credit is required.
RE: Windowskin Selection Menu - DerVVulfman - 05-23-2024
IMMEDIATE BUMP
A number of people already saw this, so a corrective bump is necessary.
The ALIGN value within the configuration system is present to make the text left, center, or right justified. Unfortunately, it was not tied to the actual method that drew the text. AKA... it didn't work.
Until now. It is a minor fix, but one that was needed.
RE: Windowskin Selection Menu - DerVVulfman - 05-23-2024
IMMEDIATE BUMP 2
Dangit, more saw before I found something needed to be added.
The list of skins did not properly sort by their ID. A sort command was missing. I minor statement of two words, this fix was needed to make the skins display in proper order.