mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
Refactor FSkin for mobile game
This commit is contained in:
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -15985,10 +15985,11 @@ forge-m-base/libs/gdx-sources.jar -text
|
|||||||
forge-m-base/libs/gdx.jar -text
|
forge-m-base/libs/gdx.jar -text
|
||||||
forge-m-base/src/forge/FScreen.java -text
|
forge-m-base/src/forge/FScreen.java -text
|
||||||
forge-m-base/src/forge/Forge.java -text
|
forge-m-base/src/forge/Forge.java -text
|
||||||
forge-m-base/src/forge/gui/shared/FSkinImage.java -text
|
forge-m-base/src/forge/assets/FSkin.java -text
|
||||||
|
forge-m-base/src/forge/assets/FSkinColor.java -text
|
||||||
|
forge-m-base/src/forge/assets/FSkinImage.java -text
|
||||||
forge-m-base/src/forge/screens/home/HomeScreen.java -text
|
forge-m-base/src/forge/screens/home/HomeScreen.java -text
|
||||||
forge-m-base/src/forge/toolbox/FButton.java -text
|
forge-m-base/src/forge/toolbox/FButton.java -text
|
||||||
forge-m-base/src/forge/toolbox/FSkin.java -text
|
|
||||||
forge-m-base/src/forge/toolbox/LayoutHelper.java -text
|
forge-m-base/src/forge/toolbox/LayoutHelper.java -text
|
||||||
forge-m-desktop/.classpath -text
|
forge-m-desktop/.classpath -text
|
||||||
forge-m-desktop/.project -text
|
forge-m-desktop/.project -text
|
||||||
|
|||||||
@@ -1342,25 +1342,26 @@ public enum FSkin {
|
|||||||
final File f = new File(preferredDir + FILE_SPLASH);
|
final File f = new File(preferredDir + FILE_SPLASH);
|
||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
FSkin.loadLight("default", onInit);
|
FSkin.loadLight("default", onInit);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
final BufferedImage img;
|
|
||||||
try {
|
|
||||||
img = ImageIO.read(f);
|
|
||||||
|
|
||||||
final int h = img.getHeight();
|
final BufferedImage img;
|
||||||
final int w = img.getWidth();
|
try {
|
||||||
|
img = ImageIO.read(f);
|
||||||
|
|
||||||
SkinIcon.setIcon(Backgrounds.BG_SPLASH, img.getSubimage(0, 0, w, h - 100));
|
final int h = img.getHeight();
|
||||||
|
final int w = img.getWidth();
|
||||||
|
|
||||||
UIManager.put("ProgressBar.background", FSkin.getColorFromPixel(img.getRGB(25, h - 75)));
|
SkinIcon.setIcon(Backgrounds.BG_SPLASH, img.getSubimage(0, 0, w, h - 100));
|
||||||
UIManager.put("ProgressBar.selectionBackground", FSkin.getColorFromPixel(img.getRGB(75, h - 75)));
|
|
||||||
UIManager.put("ProgressBar.foreground", FSkin.getColorFromPixel(img.getRGB(25, h - 25)));
|
UIManager.put("ProgressBar.background", FSkin.getColorFromPixel(img.getRGB(25, h - 75)));
|
||||||
UIManager.put("ProgressBar.selectionForeground", FSkin.getColorFromPixel(img.getRGB(75, h - 25)));
|
UIManager.put("ProgressBar.selectionBackground", FSkin.getColorFromPixel(img.getRGB(75, h - 75)));
|
||||||
UIManager.put("ProgressBar.border", new LineBorder(Color.BLACK, 0));
|
UIManager.put("ProgressBar.foreground", FSkin.getColorFromPixel(img.getRGB(25, h - 25)));
|
||||||
} catch (final IOException e) {
|
UIManager.put("ProgressBar.selectionForeground", FSkin.getColorFromPixel(img.getRGB(75, h - 25)));
|
||||||
e.printStackTrace();
|
UIManager.put("ProgressBar.border", new LineBorder(Color.BLACK, 0));
|
||||||
}
|
}
|
||||||
|
catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import java.util.Stack;
|
|||||||
|
|
||||||
import com.badlogic.gdx.Game;
|
import com.badlogic.gdx.Game;
|
||||||
|
|
||||||
|
import forge.assets.FSkin;
|
||||||
import forge.screens.home.HomeScreen;
|
import forge.screens.home.HomeScreen;
|
||||||
import forge.toolbox.FSkin;
|
|
||||||
|
|
||||||
public class Forge extends Game {
|
public class Forge extends Game {
|
||||||
private static Forge game;
|
private static Forge game;
|
||||||
@@ -22,8 +22,8 @@ public class Forge extends Game {
|
|||||||
public void create() {
|
public void create() {
|
||||||
//Gdx.graphics.setContinuousRendering(false); //save power consumption by disabling continuous rendering
|
//Gdx.graphics.setContinuousRendering(false); //save power consumption by disabling continuous rendering
|
||||||
|
|
||||||
/*FSkin.loadLight("journeyman", true);
|
FSkin.loadLight("journeyman", true);
|
||||||
FSkin.loadFull(true);*/
|
FSkin.loadFull(true);
|
||||||
openScreen(new HomeScreen());
|
openScreen(new HomeScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
428
forge-m-base/src/forge/assets/FSkin.java
Normal file
428
forge-m-base/src/forge/assets/FSkin.java
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
package forge.assets;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Application.ApplicationType;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
|
|
||||||
|
import forge.assets.FSkinImage.SourceFile;
|
||||||
|
|
||||||
|
public class FSkin {
|
||||||
|
private static final String
|
||||||
|
FILE_SKINS_DIR = "skins/",
|
||||||
|
FILE_AVATAR_SPRITE = "sprite_avatars.png",
|
||||||
|
FILE_FONT = "font1.ttf",
|
||||||
|
DEFAULT_DIR = FILE_SKINS_DIR + "default/";
|
||||||
|
|
||||||
|
private static final Map<FSkinImage, TextureRegion> images = new HashMap<FSkinImage, TextureRegion>();
|
||||||
|
private static final Map<Integer, TextureRegion> avatars = new HashMap<Integer, TextureRegion>();
|
||||||
|
|
||||||
|
private static ArrayList<String> allSkins;
|
||||||
|
private static int currentSkinIndex;
|
||||||
|
private static String preferredDir;
|
||||||
|
private static String preferredName;
|
||||||
|
private static int defaultFontSize = 12;
|
||||||
|
private static boolean loaded = false;
|
||||||
|
|
||||||
|
public static void changeSkin(final String skinName) {
|
||||||
|
/*final ForgePreferences prefs = Singletons.getModel().getPreferences();
|
||||||
|
if (skinName.equals(prefs.getPref(FPref.UI_SKIN))) { return; }
|
||||||
|
|
||||||
|
//save skin preference
|
||||||
|
prefs.setPref(FPref.UI_SKIN, skinName);
|
||||||
|
prefs.save();*/
|
||||||
|
|
||||||
|
//load skin
|
||||||
|
loaded = false; //reset this temporarily until end of loadFull()
|
||||||
|
loadLight(skinName, false);
|
||||||
|
loadFull(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads a "light" version of FSkin, just enough for the splash screen:
|
||||||
|
* skin name. Generates custom skin settings, fonts, and backgrounds.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skinName
|
||||||
|
* the skin name
|
||||||
|
*/
|
||||||
|
public static void loadLight(final String skinName, final boolean onInit) {
|
||||||
|
if (onInit) {
|
||||||
|
if (allSkins == null) { //initialize
|
||||||
|
allSkins = new ArrayList<String>();
|
||||||
|
ArrayList<String> skinDirectoryNames = getSkinDirectoryNames();
|
||||||
|
for (int i = 0; i < skinDirectoryNames.size(); i++) {
|
||||||
|
allSkins.add(skinDirectoryNames.get(i).replace('_', ' '));
|
||||||
|
}
|
||||||
|
Collections.sort(allSkins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
images.clear();
|
||||||
|
|
||||||
|
currentSkinIndex = allSkins.indexOf(skinName);
|
||||||
|
|
||||||
|
// Non-default (preferred) skin name and dir.
|
||||||
|
preferredName = skinName.toLowerCase().replace(' ', '_');
|
||||||
|
preferredDir = FILE_SKINS_DIR + preferredName + "/";
|
||||||
|
|
||||||
|
if (onInit) {
|
||||||
|
final FileHandle f = Gdx.files.internal(preferredDir + SourceFile.SPLASH.getFilename());
|
||||||
|
if (!f.exists()) {
|
||||||
|
if (!skinName.equals("default")) {
|
||||||
|
FSkin.loadLight("default", onInit);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FSkinImage image = FSkinImage.BG_SPLASH;
|
||||||
|
Texture texture = new Texture(f);
|
||||||
|
|
||||||
|
final int h = texture.getHeight();
|
||||||
|
final int w = texture.getWidth();
|
||||||
|
|
||||||
|
images.put(FSkinImage.BG_SPLASH, new TextureRegion(texture, image.getX(), image.getY(),
|
||||||
|
image.getWidth(w), image.getHeight(h)));
|
||||||
|
|
||||||
|
/*UIManager.put("ProgressBar.background", FSkin.getColorFromPixel(img.getRGB(25, h - 75)));
|
||||||
|
UIManager.put("ProgressBar.selectionBackground", FSkin.getColorFromPixel(img.getRGB(75, h - 75)));
|
||||||
|
UIManager.put("ProgressBar.foreground", FSkin.getColorFromPixel(img.getRGB(25, h - 25)));
|
||||||
|
UIManager.put("ProgressBar.selectionForeground", FSkin.getColorFromPixel(img.getRGB(75, h - 25)));
|
||||||
|
UIManager.put("ProgressBar.border", new LineBorder(Color.BLACK, 0));*/
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads two sprites: the default (which should be a complete
|
||||||
|
* collection of all symbols) and the preferred (which may be
|
||||||
|
* incomplete).
|
||||||
|
*
|
||||||
|
* Font must be present in the skin folder, and will not
|
||||||
|
* be replaced by default. The fonts are pre-derived
|
||||||
|
* in this method and saved in a HashMap for future access.
|
||||||
|
*
|
||||||
|
* Color swatches must be present in the preferred
|
||||||
|
* sprite, and will not be replaced by default.
|
||||||
|
*
|
||||||
|
* Background images must be present in skin folder,
|
||||||
|
* and will not be replaced by default.
|
||||||
|
*
|
||||||
|
* Icons, however, will be pulled from the two sprites. Obviously,
|
||||||
|
* preferred takes precedence over default, but if something is
|
||||||
|
* missing, the default picture is retrieved.
|
||||||
|
*/
|
||||||
|
public static void loadFull(final boolean onInit) {
|
||||||
|
if (onInit) {
|
||||||
|
// Preferred skin name must be called via loadLight() method,
|
||||||
|
// which does some cleanup and init work.
|
||||||
|
if (FSkin.preferredName.isEmpty()) { FSkin.loadLight("default", onInit); }
|
||||||
|
}
|
||||||
|
|
||||||
|
avatars.clear();
|
||||||
|
|
||||||
|
final Map<String, Texture> textures = new HashMap<String, Texture>();
|
||||||
|
final Map<String, Pixmap> pixmaps = new HashMap<String, Pixmap>();
|
||||||
|
|
||||||
|
//FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Processing image sprites: ", 5);
|
||||||
|
|
||||||
|
// Grab and test various sprite files.
|
||||||
|
final FileHandle f1 = Gdx.files.internal(DEFAULT_DIR + SourceFile.ICONS.getFilename());
|
||||||
|
final FileHandle f2 = Gdx.files.internal(preferredDir + SourceFile.ICONS.getFilename());
|
||||||
|
final FileHandle f3 = Gdx.files.internal(DEFAULT_DIR + SourceFile.FOILS.getFilename());
|
||||||
|
final FileHandle f4 = Gdx.files.internal(DEFAULT_DIR + FILE_AVATAR_SPRITE);
|
||||||
|
final FileHandle f5 = Gdx.files.internal(preferredDir + FILE_AVATAR_SPRITE);
|
||||||
|
final FileHandle f6 = Gdx.files.internal(DEFAULT_DIR + SourceFile.OLD_FOILS.getFilename());
|
||||||
|
|
||||||
|
try {
|
||||||
|
textures.put(f1.path(), new Texture(f1));
|
||||||
|
Pixmap preferredIcons = new Pixmap(f1);
|
||||||
|
pixmaps.put(f1.path(), preferredIcons);
|
||||||
|
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||||
|
textures.put(f2.path(), new Texture(f2));
|
||||||
|
pixmaps.put(f2.path(), new Pixmap(f2));
|
||||||
|
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||||
|
textures.put(f3.path(), new Texture(f3));
|
||||||
|
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||||
|
if (f6.exists()) {
|
||||||
|
textures.put(f6.path(), new Texture(f6));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
textures.put(f6.path(), textures.get(f3.path()));
|
||||||
|
}
|
||||||
|
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||||
|
|
||||||
|
//update colors
|
||||||
|
for (final FSkinColor.Colors c : FSkinColor.Colors.values()) {
|
||||||
|
c.setColor(FSkin.getColorFromPixel(preferredIcons.getPixel(c.getX(), c.getY())));
|
||||||
|
}
|
||||||
|
|
||||||
|
//add images besides splash background
|
||||||
|
for (FSkinImage image : FSkinImage.values()) {
|
||||||
|
if (image != FSkinImage.BG_SPLASH) {
|
||||||
|
TextureRegion textureRegion = loadTextureRegion(image, textures, pixmaps);
|
||||||
|
if (textureRegion != null) {
|
||||||
|
images.put(image, textureRegion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//assemble avatar textures
|
||||||
|
int counter = 0;
|
||||||
|
Color pxTest;
|
||||||
|
Pixmap pxDefaultAvatars, pxPreferredAvatars;
|
||||||
|
Texture txDefaultAvatars, txPreferredAvatars;
|
||||||
|
|
||||||
|
pxDefaultAvatars = new Pixmap(f4);
|
||||||
|
txDefaultAvatars = new Texture(f4);
|
||||||
|
|
||||||
|
if (f5.exists()) {
|
||||||
|
pxPreferredAvatars = new Pixmap(f5);
|
||||||
|
txPreferredAvatars = new Texture(f5);
|
||||||
|
|
||||||
|
final int pw = pxPreferredAvatars.getWidth();
|
||||||
|
final int ph = pxPreferredAvatars.getHeight();
|
||||||
|
|
||||||
|
for (int j = 0; j < ph; j += 100) {
|
||||||
|
for (int i = 0; i < pw; i += 100) {
|
||||||
|
if (i == 0 && j == 0) { continue; }
|
||||||
|
pxTest = FSkin.getColorFromPixel(pxPreferredAvatars.getPixel(i + 50, j + 50));
|
||||||
|
if (pxTest.getAlpha() == 0) { continue; }
|
||||||
|
FSkin.avatars.put(counter++, new TextureRegion(txPreferredAvatars, i, j, 100, 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pxPreferredAvatars.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int aw = pxDefaultAvatars.getWidth();
|
||||||
|
final int ah = pxDefaultAvatars.getHeight();
|
||||||
|
|
||||||
|
for (int j = 0; j < ah; j += 100) {
|
||||||
|
for (int i = 0; i < aw; i += 100) {
|
||||||
|
if (i == 0 && j == 0) { continue; }
|
||||||
|
pxTest = FSkin.getColorFromPixel(pxDefaultAvatars.getPixel(i + 50, j + 50));
|
||||||
|
if (pxTest.getAlpha() == 0) { continue; }
|
||||||
|
FSkin.avatars.put(counter++, new TextureRegion(txDefaultAvatars, i, j, 100, 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Pixmap pixmap : pixmaps.values()) {
|
||||||
|
pixmap.dispose();
|
||||||
|
}
|
||||||
|
pxDefaultAvatars.dispose();
|
||||||
|
|
||||||
|
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
System.err.println("FSkin$loadFull: Missing a sprite (default icons, "
|
||||||
|
+ "preferred icons, or foils.");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize fonts
|
||||||
|
//SkinFont.setBaseFont(GuiUtils.newFont(FILE_SKINS_DIR + preferredName + "/" + FILE_FONT));
|
||||||
|
|
||||||
|
// Run through enums and load their coords.
|
||||||
|
//Colors.updateAll();
|
||||||
|
|
||||||
|
// Images loaded; can start UI init.
|
||||||
|
//FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Creating display components.");
|
||||||
|
loaded = true;
|
||||||
|
|
||||||
|
//establish encoding symbols
|
||||||
|
/*addEncodingSymbol("W", ManaImages.IMG_WHITE);
|
||||||
|
addEncodingSymbol("U", ManaImages.IMG_BLUE);
|
||||||
|
addEncodingSymbol("B", ManaImages.IMG_BLACK);
|
||||||
|
addEncodingSymbol("R", ManaImages.IMG_RED);
|
||||||
|
addEncodingSymbol("G", ManaImages.IMG_GREEN);
|
||||||
|
addEncodingSymbol("W/U", ManaImages.IMG_WHITE_BLUE);
|
||||||
|
addEncodingSymbol("U/B", ManaImages.IMG_BLUE_BLACK);
|
||||||
|
addEncodingSymbol("B/R", ManaImages.IMG_BLACK_RED);
|
||||||
|
addEncodingSymbol("R/G", ManaImages.IMG_RED_GREEN);
|
||||||
|
addEncodingSymbol("G/W", ManaImages.IMG_GREEN_WHITE);
|
||||||
|
addEncodingSymbol("W/B", ManaImages.IMG_WHITE_BLACK);
|
||||||
|
addEncodingSymbol("U/R", ManaImages.IMG_BLUE_RED);
|
||||||
|
addEncodingSymbol("B/G", ManaImages.IMG_BLACK_GREEN);
|
||||||
|
addEncodingSymbol("R/W", ManaImages.IMG_RED_WHITE);
|
||||||
|
addEncodingSymbol("G/U", ManaImages.IMG_GREEN_BLUE);
|
||||||
|
addEncodingSymbol("2/W", ManaImages.IMG_2W);
|
||||||
|
addEncodingSymbol("2/U", ManaImages.IMG_2U);
|
||||||
|
addEncodingSymbol("2/B", ManaImages.IMG_2B);
|
||||||
|
addEncodingSymbol("2/R", ManaImages.IMG_2R);
|
||||||
|
addEncodingSymbol("2/G", ManaImages.IMG_2G);
|
||||||
|
addEncodingSymbol("W/P", ManaImages.IMG_PHRYX_WHITE);
|
||||||
|
addEncodingSymbol("U/P", ManaImages.IMG_PHRYX_BLUE);
|
||||||
|
addEncodingSymbol("B/P", ManaImages.IMG_PHRYX_BLACK);
|
||||||
|
addEncodingSymbol("R/P", ManaImages.IMG_PHRYX_RED);
|
||||||
|
addEncodingSymbol("G/P", ManaImages.IMG_PHRYX_GREEN);
|
||||||
|
for (int i = 0; i <= 20; i++) {
|
||||||
|
addEncodingSymbol(String.valueOf(i), ColorlessManaImages.valueOf("IMG_" + i));
|
||||||
|
}
|
||||||
|
addEncodingSymbol("X", ColorlessManaImages.IMG_X);
|
||||||
|
addEncodingSymbol("Y", ColorlessManaImages.IMG_Y);
|
||||||
|
addEncodingSymbol("Z", ColorlessManaImages.IMG_Z);
|
||||||
|
addEncodingSymbol("C", GameplayImages.IMG_CHAOS);
|
||||||
|
addEncodingSymbol("Q", GameplayImages.IMG_UNTAP);
|
||||||
|
addEncodingSymbol("S", GameplayImages.IMG_SNOW);
|
||||||
|
addEncodingSymbol("T", GameplayImages.IMG_TAP);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextureRegion loadTextureRegion(FSkinImage image, Map<String, Texture> textures, Map<String, Pixmap> pixmaps) {
|
||||||
|
String filename = image.getSourceFile().getFilename();
|
||||||
|
String preferredFile = preferredDir + filename;
|
||||||
|
Texture texture = null;
|
||||||
|
if (textures.containsKey(preferredFile)) {
|
||||||
|
texture = textures.get(preferredFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FileHandle file = Gdx.files.internal(preferredFile);
|
||||||
|
if (file.exists()) {
|
||||||
|
try {
|
||||||
|
texture = new Texture(file);
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
System.err.println("Failed to load skin file: " + preferredFile);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (texture != null) {
|
||||||
|
int fullWidth = texture.getWidth();
|
||||||
|
int fullHeight = texture.getHeight();
|
||||||
|
int x0 = image.getX();
|
||||||
|
int y0 = image.getY();
|
||||||
|
int w0 = image.getWidth(fullWidth);
|
||||||
|
int h0 = image.getHeight(fullHeight);
|
||||||
|
|
||||||
|
if (pixmaps.containsKey(preferredFile)) {
|
||||||
|
Pixmap pixmap = pixmaps.get(preferredFile);
|
||||||
|
|
||||||
|
// Test if requested sub-image in inside bounds of preferred sprite.
|
||||||
|
// (Height and width of preferred sprite were set in loadFontAndImages.)
|
||||||
|
if (x0 + w0 <= fullWidth && y0 + h0 <= fullHeight) {
|
||||||
|
// Test if various points of requested sub-image are transparent.
|
||||||
|
// If any return true, image exists.
|
||||||
|
int x = 0, y = 0;
|
||||||
|
Color c;
|
||||||
|
|
||||||
|
// Center
|
||||||
|
x = (x0 + w0 / 2);
|
||||||
|
y = (y0 + h0 / 2);
|
||||||
|
c = FSkin.getColorFromPixel(pixmap.getPixel(x, y));
|
||||||
|
if (c.getAlpha() != 0) { return new TextureRegion(texture, x0, y0, w0, h0); }
|
||||||
|
|
||||||
|
x += 2;
|
||||||
|
y += 2;
|
||||||
|
c = FSkin.getColorFromPixel(pixmap.getPixel(x, y));
|
||||||
|
if (c.getAlpha() != 0) { return new TextureRegion(texture, x0, y0, w0, h0); }
|
||||||
|
|
||||||
|
x -= 4;
|
||||||
|
c = FSkin.getColorFromPixel(pixmap.getPixel(x, y));
|
||||||
|
if (c.getAlpha() != 0) { return new TextureRegion(texture, x0, y0, w0, h0); }
|
||||||
|
|
||||||
|
y -= 4;
|
||||||
|
c = FSkin.getColorFromPixel(pixmap.getPixel(x, y));
|
||||||
|
if (c.getAlpha() != 0) { return new TextureRegion(texture, x0, y0, w0, h0); }
|
||||||
|
|
||||||
|
x += 4;
|
||||||
|
c = FSkin.getColorFromPixel(pixmap.getPixel(x, y));
|
||||||
|
if (c.getAlpha() != 0) { return new TextureRegion(texture, x0, y0, w0, h0); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//use default file if can't use preferred file
|
||||||
|
String defaultFile = DEFAULT_DIR + filename;
|
||||||
|
if (textures.containsKey(defaultFile)) {
|
||||||
|
texture = textures.get(defaultFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FileHandle file = Gdx.files.internal(defaultFile);
|
||||||
|
if (file.exists()) {
|
||||||
|
try {
|
||||||
|
texture = new Texture(file);
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
System.err.println("Failed to load skin file: " + defaultFile);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (texture != null) {
|
||||||
|
return new TextureRegion(texture, image.getX(), image.getY(),
|
||||||
|
image.getWidth(texture.getWidth()), image.getHeight(texture.getHeight()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name.
|
||||||
|
*
|
||||||
|
* @return Name of the current skin.
|
||||||
|
*/
|
||||||
|
public static String getName() {
|
||||||
|
return FSkin.preferredName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the skins.
|
||||||
|
*
|
||||||
|
* @return the skins
|
||||||
|
*/
|
||||||
|
public static ArrayList<String> getSkinDirectoryNames() {
|
||||||
|
final ArrayList<String> mySkins = new ArrayList<String>();
|
||||||
|
|
||||||
|
final FileHandle dir;
|
||||||
|
if (Gdx.app.getType() == ApplicationType.Desktop) {
|
||||||
|
dir = Gdx.files.internal("./bin/" + FILE_SKINS_DIR); //needed to iterate over directory for Desktop
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dir = Gdx.files.internal(FILE_SKINS_DIR);
|
||||||
|
}
|
||||||
|
if (!dir.exists() || !dir.isDirectory()) {
|
||||||
|
System.err.println("FSkin > can't find skins directory!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (FileHandle skinFile : dir.list()) {
|
||||||
|
String skinName = skinFile.name();
|
||||||
|
if (skinName.equalsIgnoreCase(".svn")) { continue; }
|
||||||
|
if (skinName.equalsIgnoreCase(".DS_Store")) { continue; }
|
||||||
|
mySkins.add(skinName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mySkins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterable<String> getAllSkins() {
|
||||||
|
return allSkins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Integer, TextureRegion> getAvatars() {
|
||||||
|
return avatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLoaded() { return loaded; }
|
||||||
|
|
||||||
|
private static Color getColorFromPixel(final int pixel) {
|
||||||
|
int r, g, b, a;
|
||||||
|
a = (pixel >> 24) & 0x000000ff;
|
||||||
|
r = (pixel >> 16) & 0x000000ff;
|
||||||
|
g = (pixel >> 8) & 0x000000ff;
|
||||||
|
b = (pixel) & 0x000000ff;
|
||||||
|
return new Color(r, g, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
212
forge-m-base/src/forge/assets/FSkinColor.java
Normal file
212
forge-m-base/src/forge/assets/FSkinColor.java
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
package forge.assets;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class FSkinColor {
|
||||||
|
public enum Colors {
|
||||||
|
CLR_THEME (70, 10),
|
||||||
|
CLR_BORDERS (70, 30),
|
||||||
|
CLR_ZEBRA (70, 50),
|
||||||
|
CLR_HOVER (70, 70),
|
||||||
|
CLR_ACTIVE (70, 90),
|
||||||
|
CLR_INACTIVE (70, 110),
|
||||||
|
CLR_TEXT (70, 130),
|
||||||
|
CLR_PHASE_INACTIVE_ENABLED (70, 150),
|
||||||
|
CLR_PHASE_INACTIVE_DISABLED (70, 170),
|
||||||
|
CLR_PHASE_ACTIVE_ENABLED (70, 190),
|
||||||
|
CLR_PHASE_ACTIVE_DISABLED (70, 210),
|
||||||
|
CLR_THEME2 (70, 230),
|
||||||
|
CLR_OVERLAY (70, 250),
|
||||||
|
CLR_COMBAT_TARGETING_ARROW (70, 270),
|
||||||
|
CLR_NORMAL_TARGETING_ARROW (70, 290);
|
||||||
|
|
||||||
|
private Color color;
|
||||||
|
private final int x, y;
|
||||||
|
|
||||||
|
/** @param xy   int[] coordinates */
|
||||||
|
Colors(final int x0, final int y0) {
|
||||||
|
x = x0;
|
||||||
|
y = y0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(Color color0) {
|
||||||
|
color = color0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final HashMap<Colors, FSkinColor> baseColors = new HashMap<Colors, FSkinColor>();
|
||||||
|
private static final HashMap<String, FSkinColor> derivedColors = new HashMap<String, FSkinColor>();
|
||||||
|
private static final int NO_BRIGHTNESS_DELTA = 0;
|
||||||
|
private static final int NO_STEP = -999; //needs to be large negative since small negative values are valid
|
||||||
|
private static final int NO_ALPHA = -1;
|
||||||
|
|
||||||
|
private final Colors baseColor;
|
||||||
|
private final int brightnessDelta;
|
||||||
|
private final int step;
|
||||||
|
private final int contrastStep;
|
||||||
|
private final int alpha;
|
||||||
|
protected Color color;
|
||||||
|
|
||||||
|
public Color getColor() { return color; }
|
||||||
|
|
||||||
|
//private constructors for color that changes with skin (use FSkin.getColor())
|
||||||
|
private FSkinColor(Colors baseColor0) {
|
||||||
|
this(baseColor0, NO_BRIGHTNESS_DELTA, NO_STEP, NO_STEP, NO_ALPHA);
|
||||||
|
}
|
||||||
|
private FSkinColor(Colors baseColor0, int brightnessDelta0, int step0, int contrastStep0, int alpha0) {
|
||||||
|
this.baseColor = baseColor0;
|
||||||
|
this.brightnessDelta = brightnessDelta0;
|
||||||
|
this.step = step0;
|
||||||
|
this.contrastStep = contrastStep0;
|
||||||
|
this.alpha = alpha0;
|
||||||
|
this.updateColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FSkinColor getDerivedColor(int brightnessDelta0, int step0, int contrastStep0, int alpha0) {
|
||||||
|
String key = this.baseColor.name() + "|" + brightnessDelta0 + "|" + step0 + "|" + contrastStep0 + "|" + alpha0;
|
||||||
|
FSkinColor derivedColor = derivedColors.get(key);
|
||||||
|
if (derivedColor == null) {
|
||||||
|
derivedColor = new FSkinColor(this.baseColor, brightnessDelta0, step0, contrastStep0, alpha0);
|
||||||
|
derivedColors.put(key, derivedColor);
|
||||||
|
}
|
||||||
|
return derivedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSkinColor brighter() {
|
||||||
|
return getDerivedColor(this.brightnessDelta + 1, this.step, this.contrastStep, this.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSkinColor darker() {
|
||||||
|
return getDerivedColor(this.brightnessDelta - 1, this.step, this.contrastStep, this.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSkinColor stepColor(int step0) {
|
||||||
|
if (this.step != NO_STEP) {
|
||||||
|
step0 += this.step;
|
||||||
|
}
|
||||||
|
return getDerivedColor(this.brightnessDelta, step0, this.contrastStep, this.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSkinColor getContrastColor(int contrastStep0) {
|
||||||
|
if (this.contrastStep != NO_STEP) {
|
||||||
|
contrastStep0 += this.contrastStep;
|
||||||
|
}
|
||||||
|
return getDerivedColor(this.brightnessDelta, this.step, contrastStep0, this.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSkinColor getHighContrastColor() {
|
||||||
|
return getContrastColor(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FSkinColor alphaColor(int alpha0) {
|
||||||
|
return getDerivedColor(this.brightnessDelta, this.step, this.contrastStep, alpha0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateColor() {
|
||||||
|
this.color = this.baseColor.color;
|
||||||
|
if (this.brightnessDelta != NO_BRIGHTNESS_DELTA) {
|
||||||
|
if (this.brightnessDelta < 0) {
|
||||||
|
for (int i = 0; i > this.brightnessDelta; i--) {
|
||||||
|
this.color = this.color.darker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < this.brightnessDelta; i++) {
|
||||||
|
this.color = this.color.brighter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.step != NO_STEP) {
|
||||||
|
this.color = FSkinColor.stepColor(this.color, this.step);
|
||||||
|
}
|
||||||
|
if (this.contrastStep != NO_STEP) {
|
||||||
|
this.color = FSkinColor.stepColor(this.color, FSkinColor.isColorBright(this.color) ? -this.contrastStep : this.contrastStep);
|
||||||
|
}
|
||||||
|
if (this.alpha != NO_ALPHA) {
|
||||||
|
this.color = FSkinColor.alphaColor(this.color, this.alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Steps RGB components of a color up or down.
|
||||||
|
* Returns opaque (non-alpha) stepped color.
|
||||||
|
* Plus for lighter, minus for darker.
|
||||||
|
*
|
||||||
|
* @param clr0 {@link java.awt.Color}
|
||||||
|
* @param step int
|
||||||
|
* @return {@link java.awt.Color}
|
||||||
|
*/
|
||||||
|
public static Color stepColor(Color clr0, int step) {
|
||||||
|
int r = clr0.getRed();
|
||||||
|
int g = clr0.getGreen();
|
||||||
|
int b = clr0.getBlue();
|
||||||
|
|
||||||
|
// Darker
|
||||||
|
if (step < 0) {
|
||||||
|
r = ((r + step > 0) ? r + step : 0);
|
||||||
|
g = ((g + step > 0) ? g + step : 0);
|
||||||
|
b = ((b + step > 0) ? b + step : 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = ((r + step < 255) ? r + step : 255);
|
||||||
|
g = ((g + step < 255) ? g + step : 255);
|
||||||
|
b = ((b + step < 255) ? b + step : 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Color(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns RGB components of a color, with a new
|
||||||
|
* value for alpha. 0 = transparent, 255 = opaque.
|
||||||
|
*
|
||||||
|
* @param clr0 {@link java.awt.Color}
|
||||||
|
* @param alpha int
|
||||||
|
* @return {@link java.awt.Color}
|
||||||
|
*/
|
||||||
|
public static Color alphaColor(Color clr0, int alpha) {
|
||||||
|
return new Color(clr0.getRed(), clr0.getGreen(), clr0.getBlue(), alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
|
||||||
|
*/
|
||||||
|
public static boolean isColorBright(Color c) {
|
||||||
|
int v = (int)Math.sqrt(
|
||||||
|
c.getRed() * c.getRed() * 0.241 +
|
||||||
|
c.getGreen() * c.getGreen() * 0.691 +
|
||||||
|
c.getBlue() * c.getBlue() * 0.068);
|
||||||
|
return v >= 130;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color getHighContrastColor(Color c) {
|
||||||
|
return isColorBright(c) ? Color.BLACK : Color.WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateAll() {
|
||||||
|
if (FSkinColor.baseColors.size() == 0) { //initialize base skin colors if needed
|
||||||
|
for (final Colors c : Colors.values()) {
|
||||||
|
FSkinColor.baseColors.put(c, new FSkinColor(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //update existing FSkinColors if baseColors already initialized
|
||||||
|
for (final FSkinColor c : FSkinColor.baseColors.values()) {
|
||||||
|
c.updateColor();
|
||||||
|
}
|
||||||
|
for (final FSkinColor c : FSkinColor.derivedColors.values()) {
|
||||||
|
c.updateColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
280
forge-m-base/src/forge/assets/FSkinImage.java
Normal file
280
forge-m-base/src/forge/assets/FSkinImage.java
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
package forge.assets;
|
||||||
|
|
||||||
|
/** Properties of various components that make up the skin.
|
||||||
|
* This interface allows all enums to be under the same roof.
|
||||||
|
* It also enforces a getter for coordinate locations in sprites. */
|
||||||
|
public enum FSkinImage {
|
||||||
|
//Backgrounds
|
||||||
|
BG_SPLASH (0, 0, 0, -100, SourceFile.SPLASH), //treat 0 and negative as offset from full width/height
|
||||||
|
BG_TEXTURE (0, 0, 0, 0, SourceFile.TEXTURE),
|
||||||
|
BG_MATCH (0, 0, 0, 0, SourceFile.MATCH),
|
||||||
|
|
||||||
|
//Zones
|
||||||
|
HAND (280, 40, 40, 40, SourceFile.ICONS),
|
||||||
|
LIBRARY (280, 0, 40, 40, SourceFile.ICONS),
|
||||||
|
EXILE (320, 40, 40, 40, SourceFile.ICONS),
|
||||||
|
FLASHBACK (280, 80, 40, 40, SourceFile.ICONS),
|
||||||
|
GRAVEYARD (320, 0, 40, 40, SourceFile.ICONS),
|
||||||
|
POISON (320, 80, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Mana symbols
|
||||||
|
MANA_COLORLESS (440, 160, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_B (360, 160, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_R (400, 160, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_U (360, 200, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_G (400, 200, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_W (440, 200, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_2B (360, 400, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_2G (400, 400, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_2R (440, 400, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_2U (440, 360, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_2W (400, 360, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_BG (360, 240, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_BR (400, 240, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_GU (360, 280, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_GW (440, 280, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_RG (360, 320, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_RW (400, 320, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_UB (440, 240, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_UR (440, 320, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_WB (400, 280, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_HYBRID_WU (360, 360, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_PHRYX_U (320, 200, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_PHRYX_W (320, 240, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_PHRYX_R (320, 280, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_PHRYX_G (320, 320, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_PHRYX_B (320, 360, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_SNOW (320, 160, 40, 40, SourceFile.ICONS),
|
||||||
|
MANA_0 (640, 200, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_1 (660, 200, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_2 (640, 220, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_3 (660, 220, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_4 (640, 240, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_5 (660, 240, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_6 (640, 260, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_7 (660, 260, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_8 (640, 280, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_9 (660, 280, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_10 (640, 300, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_11 (660, 300, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_12 (640, 320, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_13 (660, 320, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_14 (640, 340, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_15 (660, 340, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_16 (640, 360, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_17 (660, 360, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_18 (640, 380, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_19 (660, 380, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_20 (640, 400, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_X (660, 400, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_Y (640, 420, 20, 20, SourceFile.ICONS),
|
||||||
|
MANA_Z (660, 420, 20, 20, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Gameplay
|
||||||
|
TAP (640, 440, 20, 20, SourceFile.ICONS),
|
||||||
|
UNTAP (660, 440, 20, 20, SourceFile.ICONS),
|
||||||
|
CHAOS (320, 400, 40, 40, SourceFile.ICONS),
|
||||||
|
SLASH (660, 400, 10, 13, SourceFile.ICONS),
|
||||||
|
ATTACK (160, 320, 80, 80, SourceFile.ICONS),
|
||||||
|
DEFEND (160, 400, 80, 80, SourceFile.ICONS),
|
||||||
|
SUMMONSICK (240, 400, 80, 80, SourceFile.ICONS),
|
||||||
|
PHASING (240, 320, 80, 80, SourceFile.ICONS),
|
||||||
|
COSTRESERVED (240, 240, 80, 80, SourceFile.ICONS),
|
||||||
|
COUNTERS1 (0, 320, 80, 80, SourceFile.ICONS),
|
||||||
|
COUNTERS2 (0, 400, 80, 80, SourceFile.ICONS),
|
||||||
|
COUNTERS3 (80, 320, 80, 80, SourceFile.ICONS),
|
||||||
|
COUNTERS_MULTI (80, 400, 80, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Dock Icons
|
||||||
|
SHORTCUTS (160, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
SETTINGS (80, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
ENDTURN (320, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
CONCEDE (240, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
REVERTLAYOUT (400, 720, 80, 80, SourceFile.ICONS),
|
||||||
|
OPENLAYOUT (0, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
SAVELAYOUT (80, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
DECKLIST (400, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
ALPHASTRIKE (160, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
ARCSOFF (240, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
ARCSON (320, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
ARCSHOVER (400, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Quest Icons
|
||||||
|
QUEST_ZEP (0, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_GEAR (80, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_GOLD (160, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_ELIXIR (240, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_BOOK (320, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_BOTTLES (400, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_BOX (480, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_COIN (560, 480, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_CHARM (480, 800, 80, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
QUEST_FOX (0, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_LEAF (80, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_LIFE (160, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_COINSTACK (240, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_MAP (320, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_NOTES (400, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_HEART (480, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_BREW (560, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_STAKES (400, 560, 80, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
QUEST_MINUS (560, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_PLUS (480, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
QUEST_PLUSPLUS (480, 720, 80, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Interface icons
|
||||||
|
QUESTION (560, 800, 32, 32, SourceFile.ICONS),
|
||||||
|
INFORMATION (592, 800, 32, 32, SourceFile.ICONS),
|
||||||
|
WARNING (560, 832, 32, 32, SourceFile.ICONS),
|
||||||
|
ERROR (592, 832, 32, 32, SourceFile.ICONS),
|
||||||
|
DELETE (640, 480, 20, 20, SourceFile.ICONS),
|
||||||
|
DELETE_OVER (660, 480, 20, 20, SourceFile.ICONS),
|
||||||
|
EDIT (640, 500, 20, 20, SourceFile.ICONS),
|
||||||
|
EDIT_OVER (660, 500, 20, 20, SourceFile.ICONS),
|
||||||
|
OPEN (660, 520, 20, 20, SourceFile.ICONS),
|
||||||
|
MINUS (660, 620, 20, 20, SourceFile.ICONS),
|
||||||
|
NEW (660, 540, 20, 20, SourceFile.ICONS),
|
||||||
|
PLUS (660, 600, 20, 20, SourceFile.ICONS),
|
||||||
|
PRINT (660, 640, 20, 20, SourceFile.ICONS),
|
||||||
|
SAVE (660, 560, 20, 20, SourceFile.ICONS),
|
||||||
|
SAVEAS (660, 580, 20, 20, SourceFile.ICONS),
|
||||||
|
CLOSE (640, 640, 20, 20, SourceFile.ICONS),
|
||||||
|
LIST (640, 660, 20, 20, SourceFile.ICONS),
|
||||||
|
CARD_IMAGE (660, 660, 20, 20, SourceFile.ICONS),
|
||||||
|
UNKNOWN (0, 720, 80, 80, SourceFile.ICONS),
|
||||||
|
LOGO (480, 0, 200, 200, SourceFile.ICONS),
|
||||||
|
FLIPCARD (400, 0, 80, 120, SourceFile.ICONS),
|
||||||
|
FAVICON (0, 640, 80, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Layout images
|
||||||
|
HANDLE (320, 450, 80, 20, SourceFile.ICONS),
|
||||||
|
CUR_L (564, 724, 32, 32, SourceFile.ICONS),
|
||||||
|
CUR_R (564, 764, 32, 32, SourceFile.ICONS),
|
||||||
|
CUR_T (604, 724, 32, 32, SourceFile.ICONS),
|
||||||
|
CUR_B (604, 764, 32, 32, SourceFile.ICONS),
|
||||||
|
CUR_TAB (644, 764, 32, 32, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Editor images
|
||||||
|
STAR_OUTINE (640, 460, 20, 20, SourceFile.ICONS),
|
||||||
|
STAR_FILLED (660, 460, 20, 20, SourceFile.ICONS),
|
||||||
|
ARTIFACT (280, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
CREATURE (240, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
ENCHANTMENT (320, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
INSTANT (360, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
LAND (120, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
MULTI (80, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
PLANESWALKER (200, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
PACK (80, 760, 40, 40, SourceFile.ICONS),
|
||||||
|
SORCERY (160, 720, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Buttons
|
||||||
|
BTN_START_UP (480, 200, 160, 80, SourceFile.ICONS),
|
||||||
|
BTN_START_OVER (480, 280, 160, 80, SourceFile.ICONS),
|
||||||
|
BTN_START_DOWN (480, 360, 160, 80, SourceFile.ICONS),
|
||||||
|
|
||||||
|
BTN_UP_LEFT (80, 0, 40, 40, SourceFile.ICONS),
|
||||||
|
BTN_UP_CENTER (120, 0, 1, 40, SourceFile.ICONS),
|
||||||
|
BTN_UP_RIGHT (160, 0, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
BTN_OVER_LEFT (80, 40, 40, 40, SourceFile.ICONS),
|
||||||
|
BTN_OVER_CENTER (120, 40, 1, 40, SourceFile.ICONS),
|
||||||
|
BTN_OVER_RIGHT (160, 40, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
BTN_DOWN_LEFT (80, 80, 40, 40, SourceFile.ICONS),
|
||||||
|
BTN_DOWN_CENTER (120, 80, 1, 40, SourceFile.ICONS),
|
||||||
|
BTN_DOWN_RIGHT (160, 80, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
BTN_FOCUS_LEFT (80, 120, 40, 40, SourceFile.ICONS),
|
||||||
|
BTN_FOCUS_CENTER (120, 120, 1, 40, SourceFile.ICONS),
|
||||||
|
BTN_FOCUS_RIGHT (160, 120, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
BTN_TOGGLE_LEFT (80, 160, 40, 40, SourceFile.ICONS),
|
||||||
|
BTN_TOGGLE_CENTER (120, 160, 1, 40, SourceFile.ICONS),
|
||||||
|
BTN_TOGGLE_RIGHT (160, 160, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
BTN_DISABLED_LEFT (80, 200, 40, 40, SourceFile.ICONS),
|
||||||
|
BTN_DISABLED_CENTER (120, 200, 1, 40, SourceFile.ICONS),
|
||||||
|
BTN_DISABLED_RIGHT (160, 200, 40, 40, SourceFile.ICONS),
|
||||||
|
|
||||||
|
//Foils
|
||||||
|
FOIL_01 (0, 0, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_02 (400, 0, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_03 (0, 570, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_04 (400, 570, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_05 (0, 1140, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_06 (400, 1140, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_07 (0, 1710, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_08 (400, 1710, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_09 (0, 2280, 400, 570, SourceFile.FOILS),
|
||||||
|
FOIL_10 (400, 2280, 400, 570, SourceFile.FOILS),
|
||||||
|
|
||||||
|
//Old Foils
|
||||||
|
FOIL_11 (0, 0, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_12 (400, 0, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_13 (0, 570, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_14 (400, 570, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_15 (0, 1140, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_16 (400, 1140, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_17 (0, 1710, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_18 (400, 1710, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_19 (0, 2280, 400, 570, SourceFile.OLD_FOILS),
|
||||||
|
FOIL_20 (400, 2280, 400, 570, SourceFile.OLD_FOILS);
|
||||||
|
|
||||||
|
public enum SourceFile {
|
||||||
|
ICONS("sprite_icons.png"),
|
||||||
|
FOILS("sprite_foils.png"),
|
||||||
|
OLD_FOILS("sprite_old_foils.png"),
|
||||||
|
SPLASH("bg_splash.png"),
|
||||||
|
MATCH("bg_match.jpg"),
|
||||||
|
TEXTURE("bg_texture.jpg");
|
||||||
|
|
||||||
|
private final String filename;
|
||||||
|
|
||||||
|
SourceFile(String filename0) {
|
||||||
|
filename = filename0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int x, y, w, h;
|
||||||
|
private final SourceFile sourceFile;
|
||||||
|
|
||||||
|
FSkinImage(int x0, int y0, int w0, int h0, SourceFile sourceFile0) {
|
||||||
|
x = x0;
|
||||||
|
y = y0;
|
||||||
|
w = w0;
|
||||||
|
h = h0;
|
||||||
|
sourceFile = sourceFile0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth(int fullWidth) {
|
||||||
|
if (w > 0) {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
return fullWidth + w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight(int fullHeight) {
|
||||||
|
if (h > 0) {
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
return fullHeight + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceFile getSourceFile() {
|
||||||
|
return sourceFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
package forge.gui.shared;
|
|
||||||
|
|
||||||
/** Properties of various components that make up the skin.
|
|
||||||
* This interface allows all enums to be under the same roof.
|
|
||||||
* It also enforces a getter for coordinate locations in sprites. */
|
|
||||||
public enum FSkinImage {
|
|
||||||
//Zones
|
|
||||||
HAND (280, 40, 40, 40),
|
|
||||||
LIBRARY (280, 0, 40, 40),
|
|
||||||
EXILE (320, 40, 40, 40),
|
|
||||||
FLASHBACK (280, 80, 40, 40),
|
|
||||||
GRAVEYARD (320, 0, 40, 40),
|
|
||||||
POISON (320, 80, 40, 40),
|
|
||||||
|
|
||||||
//Mana symbols
|
|
||||||
MANA_COLORLESS (440, 160, 40, 40),
|
|
||||||
MANA_B (360, 160, 40, 40),
|
|
||||||
MANA_R (400, 160, 40, 40),
|
|
||||||
MANA_U (360, 200, 40, 40),
|
|
||||||
MANA_G (400, 200, 40, 40),
|
|
||||||
MANA_W (440, 200, 40, 40),
|
|
||||||
MANA_2B (360, 400, 40, 40),
|
|
||||||
MANA_2G (400, 400, 40, 40),
|
|
||||||
MANA_2R (440, 400, 40, 40),
|
|
||||||
MANA_2U (440, 360, 40, 40),
|
|
||||||
MANA_2W (400, 360, 40, 40),
|
|
||||||
MANA_HYBRID_BG (360, 240, 40, 40),
|
|
||||||
MANA_HYBRID_BR (400, 240, 40, 40),
|
|
||||||
MANA_HYBRID_GU (360, 280, 40, 40),
|
|
||||||
MANA_HYBRID_GW (440, 280, 40, 40),
|
|
||||||
MANA_HYBRID_RG (360, 320, 40, 40),
|
|
||||||
MANA_HYBRID_RW (400, 320, 40, 40),
|
|
||||||
MANA_HYBRID_UB (440, 240, 40, 40),
|
|
||||||
MANA_HYBRID_UR (440, 320, 40, 40),
|
|
||||||
MANA_HYBRID_WB (400, 280, 40, 40),
|
|
||||||
MANA_HYBRID_WU (360, 360, 40, 40),
|
|
||||||
MANA_PHRYX_U (320, 200, 40, 40),
|
|
||||||
MANA_PHRYX_W (320, 240, 40, 40),
|
|
||||||
MANA_PHRYX_R (320, 280, 40, 40),
|
|
||||||
MANA_PHRYX_G (320, 320, 40, 40),
|
|
||||||
MANA_PHRYX_B (320, 360, 40, 40),
|
|
||||||
MANA_SNOW (320, 160, 40, 40),
|
|
||||||
MANA_0 (640, 200, 20, 20),
|
|
||||||
MANA_1 (660, 200, 20, 20),
|
|
||||||
MANA_2 (640, 220, 20, 20),
|
|
||||||
MANA_3 (660, 220, 20, 20),
|
|
||||||
MANA_4 (640, 240, 20, 20),
|
|
||||||
MANA_5 (660, 240, 20, 20),
|
|
||||||
MANA_6 (640, 260, 20, 20),
|
|
||||||
MANA_7 (660, 260, 20, 20),
|
|
||||||
MANA_8 (640, 280, 20, 20),
|
|
||||||
MANA_9 (660, 280, 20, 20),
|
|
||||||
MANA_10 (640, 300, 20, 20),
|
|
||||||
MANA_11 (660, 300, 20, 20),
|
|
||||||
MANA_12 (640, 320, 20, 20),
|
|
||||||
MANA_13 (660, 320, 20, 20),
|
|
||||||
MANA_14 (640, 340, 20, 20),
|
|
||||||
MANA_15 (660, 340, 20, 20),
|
|
||||||
MANA_16 (640, 360, 20, 20),
|
|
||||||
MANA_17 (660, 360, 20, 20),
|
|
||||||
MANA_18 (640, 380, 20, 20),
|
|
||||||
MANA_19 (660, 380, 20, 20),
|
|
||||||
MANA_20 (640, 400, 20, 20),
|
|
||||||
MANA_X (660, 400, 20, 20),
|
|
||||||
MANA_Y (640, 420, 20, 20),
|
|
||||||
MANA_Z (660, 420, 20, 20),
|
|
||||||
|
|
||||||
//Gameplay
|
|
||||||
TAP (640, 440, 20, 20),
|
|
||||||
UNTAP (660, 440, 20, 20),
|
|
||||||
CHAOS (320, 400, 40, 40),
|
|
||||||
SLASH (660, 400, 10, 13),
|
|
||||||
ATTACK (160, 320, 80, 80),
|
|
||||||
DEFEND (160, 400, 80, 80),
|
|
||||||
SUMMONSICK (240, 400, 80, 80),
|
|
||||||
PHASING (240, 320, 80, 80),
|
|
||||||
COSTRESERVED (240, 240, 80, 80),
|
|
||||||
COUNTERS1 (0, 320, 80, 80),
|
|
||||||
COUNTERS2 (0, 400, 80, 80),
|
|
||||||
COUNTERS3 (80, 320, 80, 80),
|
|
||||||
COUNTERS_MULTI (80, 400, 80, 80),
|
|
||||||
|
|
||||||
//Foils
|
|
||||||
FOIL_01 (0, 0, 400, 570),
|
|
||||||
FOIL_02 (400, 0, 400, 570),
|
|
||||||
FOIL_03 (0, 570, 400, 570),
|
|
||||||
FOIL_04 (400, 570, 400, 570),
|
|
||||||
FOIL_05 (0, 1140, 400, 570),
|
|
||||||
FOIL_06 (400, 1140, 400, 570),
|
|
||||||
FOIL_07 (0, 1710, 400, 570),
|
|
||||||
FOIL_08 (400, 1710, 400, 570),
|
|
||||||
FOIL_09 (0, 2280, 400, 570),
|
|
||||||
FOIL_10 (400, 2280, 400, 570),
|
|
||||||
|
|
||||||
//Old Foils
|
|
||||||
FOIL_11 (0, 0, 400, 570),
|
|
||||||
FOIL_12 (400, 0, 400, 570),
|
|
||||||
FOIL_13 (0, 570, 400, 570),
|
|
||||||
FOIL_14 (400, 570, 400, 570),
|
|
||||||
FOIL_15 (0, 1140, 400, 570),
|
|
||||||
FOIL_16 (400, 1140, 400, 570),
|
|
||||||
FOIL_17 (0, 1710, 400, 570),
|
|
||||||
FOIL_18 (400, 1710, 400, 570),
|
|
||||||
FOIL_19 (0, 2280, 400, 570),
|
|
||||||
FOIL_20 (400, 2280, 400, 570),
|
|
||||||
|
|
||||||
//Dock Icons
|
|
||||||
SHORTCUTS (160, 640, 80, 80),
|
|
||||||
SETTINGS (80, 640, 80, 80),
|
|
||||||
ENDTURN (320, 640, 80, 80),
|
|
||||||
CONCEDE (240, 640, 80, 80),
|
|
||||||
REVERTLAYOUT (400, 720, 80, 80),
|
|
||||||
OPENLAYOUT (0, 800, 80, 80),
|
|
||||||
SAVELAYOUT (80, 800, 80, 80),
|
|
||||||
DECKLIST (400, 640, 80, 80),
|
|
||||||
ALPHASTRIKE (160, 800, 80, 80),
|
|
||||||
ARCSOFF (240, 800, 80, 80),
|
|
||||||
ARCSON (320, 800, 80, 80),
|
|
||||||
ARCSHOVER (400, 800, 80, 80),
|
|
||||||
|
|
||||||
//Quest Icons
|
|
||||||
QUEST_ZEP (0, 480, 80, 80),
|
|
||||||
QUEST_GEAR (80, 480, 80, 80),
|
|
||||||
QUEST_GOLD (160, 480, 80, 80),
|
|
||||||
QUEST_ELIXIR (240, 480, 80, 80),
|
|
||||||
QUEST_BOOK (320, 480, 80, 80),
|
|
||||||
QUEST_BOTTLES (400, 480, 80, 80),
|
|
||||||
QUEST_BOX (480, 480, 80, 80),
|
|
||||||
QUEST_COIN (560, 480, 80, 80),
|
|
||||||
QUEST_CHARM (480, 800, 80, 80),
|
|
||||||
|
|
||||||
QUEST_FOX (0, 560, 80, 80),
|
|
||||||
QUEST_LEAF (80, 560, 80, 80),
|
|
||||||
QUEST_LIFE (160, 560, 80, 80),
|
|
||||||
QUEST_COINSTACK (240, 560, 80, 80),
|
|
||||||
QUEST_MAP (320, 560, 80, 80),
|
|
||||||
QUEST_NOTES (400, 560, 80, 80),
|
|
||||||
QUEST_HEART (480, 560, 80, 80),
|
|
||||||
QUEST_BREW (560, 560, 80, 80),
|
|
||||||
QUEST_STAKES (400, 560, 80, 80),
|
|
||||||
|
|
||||||
QUEST_MINUS (560, 640, 80, 80),
|
|
||||||
QUEST_PLUS (480, 640, 80, 80),
|
|
||||||
QUEST_PLUSPLUS (480, 720, 80, 80),
|
|
||||||
|
|
||||||
//Interface icons
|
|
||||||
QUESTION (560, 800, 32, 32),
|
|
||||||
INFORMATION (592, 800, 32, 32),
|
|
||||||
WARNING (560, 832, 32, 32),
|
|
||||||
ERROR (592, 832, 32, 32),
|
|
||||||
DELETE (640, 480, 20, 20),
|
|
||||||
DELETE_OVER (660, 480, 20, 20),
|
|
||||||
EDIT (640, 500, 20, 20),
|
|
||||||
EDIT_OVER (660, 500, 20, 20),
|
|
||||||
OPEN (660, 520, 20, 20),
|
|
||||||
MINUS (660, 620, 20, 20),
|
|
||||||
NEW (660, 540, 20, 20),
|
|
||||||
PLUS (660, 600, 20, 20),
|
|
||||||
PRINT (660, 640, 20, 20),
|
|
||||||
SAVE (660, 560, 20, 20),
|
|
||||||
SAVEAS (660, 580, 20, 20),
|
|
||||||
CLOSE (640, 640, 20, 20),
|
|
||||||
LIST (640, 660, 20, 20),
|
|
||||||
CARD_IMAGE (660, 660, 20, 20),
|
|
||||||
UNKNOWN (0, 720, 80, 80),
|
|
||||||
LOGO (480, 0, 200, 200),
|
|
||||||
FLIPCARD (400, 0, 80, 120),
|
|
||||||
FAVICON (0, 640, 80, 80),
|
|
||||||
|
|
||||||
//Layout images
|
|
||||||
HANDLE (320, 450, 80, 20),
|
|
||||||
CUR_L (564, 724, 32, 32),
|
|
||||||
CUR_R (564, 764, 32, 32),
|
|
||||||
CUR_T (604, 724, 32, 32),
|
|
||||||
CUR_B (604, 764, 32, 32),
|
|
||||||
CUR_TAB (644, 764, 32, 32),
|
|
||||||
|
|
||||||
//Editor images
|
|
||||||
STAR_OUTINE (640, 460, 20, 20),
|
|
||||||
STAR_FILLED (660, 460, 20, 20),
|
|
||||||
ARTIFACT (280, 720, 40, 40),
|
|
||||||
CREATURE (240, 720, 40, 40),
|
|
||||||
ENCHANTMENT (320, 720, 40, 40),
|
|
||||||
INSTANT (360, 720, 40, 40),
|
|
||||||
LAND (120, 720, 40, 40),
|
|
||||||
MULTI (80, 720, 40, 40),
|
|
||||||
PLANESWALKER (200, 720, 40, 40),
|
|
||||||
PACK (80, 760, 40, 40),
|
|
||||||
SORCERY (160, 720, 40, 40),
|
|
||||||
|
|
||||||
//Buttons
|
|
||||||
BTN_START_UP (480, 200, 160, 80),
|
|
||||||
BTN_START_OVER (480, 280, 160, 80),
|
|
||||||
BTN_START_DOWN (480, 360, 160, 80),
|
|
||||||
|
|
||||||
BTN_UP_LEFT (80, 0, 40, 40),
|
|
||||||
BTN_UP_CENTER (120, 0, 1, 40),
|
|
||||||
BTN_UP_RIGHT (160, 0, 40, 40),
|
|
||||||
|
|
||||||
BTN_OVER_LEFT (80, 40, 40, 40),
|
|
||||||
BTN_OVER_CENTER (120, 40, 1, 40),
|
|
||||||
BTN_OVER_RIGHT (160, 40, 40, 40),
|
|
||||||
|
|
||||||
BTN_DOWN_LEFT (80, 80, 40, 40),
|
|
||||||
BTN_DOWN_CENTER (120, 80, 1, 40),
|
|
||||||
BTN_DOWN_RIGHT (160, 80, 40, 40),
|
|
||||||
|
|
||||||
BTN_FOCUS_LEFT (80, 120, 40, 40),
|
|
||||||
BTN_FOCUS_CENTER (120, 120, 1, 40),
|
|
||||||
BTN_FOCUS_RIGHT (160, 120, 40, 40),
|
|
||||||
|
|
||||||
BTN_TOGGLE_LEFT (80, 160, 40, 40),
|
|
||||||
BTN_TOGGLE_CENTER (120, 160, 1, 40),
|
|
||||||
BTN_TOGGLE_RIGHT (160, 160, 40, 40),
|
|
||||||
|
|
||||||
BTN_DISABLED_LEFT (80, 200, 40, 40),
|
|
||||||
BTN_DISABLED_CENTER (120, 200, 1, 40),
|
|
||||||
BTN_DISABLED_RIGHT (160, 200, 40, 40);
|
|
||||||
|
|
||||||
private int x, y, w, h;
|
|
||||||
|
|
||||||
FSkinImage(int x0, int y0, int w0, int h0) {
|
|
||||||
x = x0;
|
|
||||||
y = y0;
|
|
||||||
w = w0;
|
|
||||||
h = h0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,373 +0,0 @@
|
|||||||
package forge.toolbox;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Font;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.Application.ApplicationType;
|
|
||||||
import com.badlogic.gdx.Gdx;
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
|
||||||
import com.badlogic.gdx.graphics.Pixmap;
|
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|
||||||
|
|
||||||
public class FSkin {
|
|
||||||
/*private static final String
|
|
||||||
FILE_SKINS_DIR = "skins/",
|
|
||||||
FILE_ICON_SPRITE = "sprite_icons.png",
|
|
||||||
FILE_FOIL_SPRITE = "sprite_foils.png",
|
|
||||||
FILE_OLD_FOIL_SPRITE = "sprite_old_foils.png",
|
|
||||||
FILE_AVATAR_SPRITE = "sprite_avatars.png",
|
|
||||||
FILE_FONT = "font1.ttf",
|
|
||||||
FILE_SPLASH = "bg_splash.png",
|
|
||||||
FILE_MATCH_BG = "bg_match.jpg",
|
|
||||||
FILE_TEXTURE_BG = "bg_texture.jpg",
|
|
||||||
DEFAULT_DIR = FILE_SKINS_DIR + "default/";
|
|
||||||
|
|
||||||
private static ArrayList<String> allSkins;
|
|
||||||
private static int currentSkinIndex;
|
|
||||||
private static String preferredDir;
|
|
||||||
private static String preferredName;
|
|
||||||
private static Pixmap pxDefaultSprite, pxPreferredSprite, pxDefaultAvatars, pxPreferredAvatars;
|
|
||||||
private static Texture txDefaultSprite, txPreferredSprite, txFoils, txOldFoils, txDefaultAvatars, txPreferredAvatars;
|
|
||||||
private static int defaultFontSize = 12;
|
|
||||||
private static boolean loaded = false;
|
|
||||||
|
|
||||||
public static void changeSkin(final String skinName) {
|
|
||||||
final ForgePreferences prefs = Singletons.getModel().getPreferences();
|
|
||||||
if (skinName.equals(prefs.getPref(FPref.UI_SKIN))) { return; }
|
|
||||||
|
|
||||||
//save skin preference
|
|
||||||
prefs.setPref(FPref.UI_SKIN, skinName);
|
|
||||||
prefs.save();
|
|
||||||
|
|
||||||
//load skin
|
|
||||||
loaded = false; //reset this temporarily until end of loadFull()
|
|
||||||
loadLight(skinName, false);
|
|
||||||
loadFull(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Loads a "light" version of FSkin, just enough for the splash screen:
|
|
||||||
* skin name. Generates custom skin settings, fonts, and backgrounds.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param skinName
|
|
||||||
* the skin name
|
|
||||||
*//*
|
|
||||||
public static void loadLight(final String skinName, final boolean onInit) {
|
|
||||||
if (onInit) {
|
|
||||||
if (allSkins == null) { //initialize
|
|
||||||
allSkins = new ArrayList<String>();
|
|
||||||
ArrayList<String> skinDirectoryNames = getSkinDirectoryNames();
|
|
||||||
for (int i = 0; i < skinDirectoryNames.size(); i++) {
|
|
||||||
allSkins.add(WordUtils.capitalize(skinDirectoryNames.get(i).replace('_', ' ')));
|
|
||||||
}
|
|
||||||
Collections.sort(allSkins);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentSkinIndex = allSkins.indexOf(skinName);
|
|
||||||
|
|
||||||
// Non-default (preferred) skin name and dir.
|
|
||||||
FSkin.preferredName = skinName.toLowerCase().replace(' ', '_');
|
|
||||||
FSkin.preferredDir = FILE_SKINS_DIR + preferredName + "/";
|
|
||||||
|
|
||||||
if (onInit) {
|
|
||||||
final FileHandle f = Gdx.files.internal(preferredDir + FILE_SPLASH);
|
|
||||||
if (!f.exists()) {
|
|
||||||
FSkin.loadLight("default", onInit);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final Texture img;
|
|
||||||
try {
|
|
||||||
img = new Texture(f);
|
|
||||||
|
|
||||||
final int h = img.getHeight();
|
|
||||||
final int w = img.getWidth();
|
|
||||||
|
|
||||||
SkinImage.setImage(Backgrounds.BG_SPLASH, new TextureRegion(img, 0, 0, w, h - 100));
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Loads two sprites: the default (which should be a complete
|
|
||||||
* collection of all symbols) and the preferred (which may be
|
|
||||||
* incomplete).
|
|
||||||
*
|
|
||||||
* Font must be present in the skin folder, and will not
|
|
||||||
* be replaced by default. The fonts are pre-derived
|
|
||||||
* in this method and saved in a HashMap for future access.
|
|
||||||
*
|
|
||||||
* Color swatches must be present in the preferred
|
|
||||||
* sprite, and will not be replaced by default.
|
|
||||||
*
|
|
||||||
* Background images must be present in skin folder,
|
|
||||||
* and will not be replaced by default.
|
|
||||||
*
|
|
||||||
* Icons, however, will be pulled from the two sprites. Obviously,
|
|
||||||
* preferred takes precedence over default, but if something is
|
|
||||||
* missing, the default picture is retrieved.
|
|
||||||
*//*
|
|
||||||
public static void loadFull(final boolean onInit) {
|
|
||||||
if (onInit) {
|
|
||||||
// Preferred skin name must be called via loadLight() method,
|
|
||||||
// which does some cleanup and init work.
|
|
||||||
if (FSkin.preferredName.isEmpty()) { FSkin.loadLight("default", onInit); }
|
|
||||||
}
|
|
||||||
|
|
||||||
//FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Processing image sprites: ", 5);
|
|
||||||
|
|
||||||
// Grab and test various sprite files.
|
|
||||||
final FileHandle f1 = Gdx.files.internal(DEFAULT_DIR + FILE_ICON_SPRITE);
|
|
||||||
final FileHandle f2 = Gdx.files.internal(preferredDir + FILE_ICON_SPRITE);
|
|
||||||
final FileHandle f3 = Gdx.files.internal(DEFAULT_DIR + FILE_FOIL_SPRITE);
|
|
||||||
final FileHandle f4 = Gdx.files.internal(DEFAULT_DIR + FILE_AVATAR_SPRITE);
|
|
||||||
final FileHandle f5 = Gdx.files.internal(preferredDir + FILE_AVATAR_SPRITE);
|
|
||||||
final FileHandle f6 = Gdx.files.internal(DEFAULT_DIR + FILE_OLD_FOIL_SPRITE);
|
|
||||||
|
|
||||||
try {
|
|
||||||
pxDefaultSprite = new Pixmap(f1);
|
|
||||||
txDefaultSprite = new Texture(f1);
|
|
||||||
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
|
||||||
pxPreferredSprite = new Pixmap(f2);
|
|
||||||
txPreferredSprite = new Texture(f2);
|
|
||||||
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
|
||||||
txFoils = new Texture(f3);
|
|
||||||
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
|
||||||
txOldFoils = f6.exists() ? new Texture(f6) : new Texture(f3);
|
|
||||||
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
|
||||||
pxDefaultAvatars = new Pixmap(f4);
|
|
||||||
txDefaultAvatars = new Texture(f4);
|
|
||||||
|
|
||||||
if (f5.exists()) {
|
|
||||||
pxDefaultAvatars = new Pixmap(f5);
|
|
||||||
txPreferredAvatars = new Texture(f5);
|
|
||||||
}
|
|
||||||
|
|
||||||
//FView.SINGLETON_INSTANCE.incrementSplashProgessBar(++p);
|
|
||||||
}
|
|
||||||
catch (final Exception e) {
|
|
||||||
System.err.println("FSkin$loadFull: Missing a sprite (default icons, "
|
|
||||||
+ "preferred icons, or foils.");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize fonts
|
|
||||||
if (onInit) { //set default font size only once onInit
|
|
||||||
Font f = UIManager.getDefaults().getFont("Label.font");
|
|
||||||
if (f != null) {
|
|
||||||
FSkin.defaultFontSize = f.getSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SkinFont.setBaseFont(GuiUtils.newFont(FILE_SKINS_DIR + preferredName + "/" + FILE_FONT));
|
|
||||||
|
|
||||||
// Put various images into map (except sprite and splash).
|
|
||||||
// Exceptions handled inside method.
|
|
||||||
SkinImage.setImage(Backgrounds.BG_TEXTURE, new TextureRegion(new Texture(preferredDir + FILE_TEXTURE_BG)));
|
|
||||||
SkinImage.setImage(Backgrounds.BG_MATCH, new TextureRegion(new Texture(preferredDir + FILE_MATCH_BG)));
|
|
||||||
|
|
||||||
// Run through enums and load their coords.
|
|
||||||
Colors.updateAll();
|
|
||||||
for (final ZoneImages e : ZoneImages.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final DockIcons e : DockIcons.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final InterfaceIcons e : InterfaceIcons.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final ButtonImages e : ButtonImages.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final QuestIcons e : QuestIcons.values()) { SkinImage.setImage(e); }
|
|
||||||
|
|
||||||
for (final EditorImages e : EditorImages.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final ManaImages e : ManaImages.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final ColorlessManaImages e : ColorlessManaImages.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final GameplayImages e : GameplayImages.values()) { SkinImage.setImage(e); }
|
|
||||||
for (final LayoutImages e : LayoutImages.values()) { SkinImage.setImage(e); }
|
|
||||||
|
|
||||||
// Foils have a separate sprite, so uses a specific method.
|
|
||||||
for (final Foils e : Foils.values()) { FSkin.setFoil(e, false); }
|
|
||||||
for (final OldFoils e : OldFoils.values()) { FSkin.setFoil(e, true); }
|
|
||||||
|
|
||||||
// Assemble avatar images
|
|
||||||
FSkin.assembleAvatars();
|
|
||||||
|
|
||||||
// Images loaded; can start UI init.
|
|
||||||
//FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Creating display components.");
|
|
||||||
loaded = true;
|
|
||||||
|
|
||||||
// Clear references to pixmap
|
|
||||||
pxDefaultSprite.dispose();
|
|
||||||
pxDefaultSprite = null;
|
|
||||||
pxPreferredSprite.dispose();
|
|
||||||
pxPreferredSprite = null;
|
|
||||||
pxDefaultAvatars.dispose();
|
|
||||||
pxDefaultAvatars = null;
|
|
||||||
if (pxPreferredAvatars != null) {
|
|
||||||
pxPreferredAvatars.dispose();
|
|
||||||
pxPreferredAvatars = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//establish encoding symbols
|
|
||||||
FileHandle dir = Gdx.files.internal(NewConstants.CACHE_SYMBOLS_DIR);
|
|
||||||
if (!dir.mkdir()) { //ensure symbols directory exists and is empty
|
|
||||||
for (FileHandle file : dir.listFileHandles()) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addEncodingSymbol("W", ManaImages.IMG_WHITE);
|
|
||||||
addEncodingSymbol("U", ManaImages.IMG_BLUE);
|
|
||||||
addEncodingSymbol("B", ManaImages.IMG_BLACK);
|
|
||||||
addEncodingSymbol("R", ManaImages.IMG_RED);
|
|
||||||
addEncodingSymbol("G", ManaImages.IMG_GREEN);
|
|
||||||
addEncodingSymbol("W/U", ManaImages.IMG_WHITE_BLUE);
|
|
||||||
addEncodingSymbol("U/B", ManaImages.IMG_BLUE_BLACK);
|
|
||||||
addEncodingSymbol("B/R", ManaImages.IMG_BLACK_RED);
|
|
||||||
addEncodingSymbol("R/G", ManaImages.IMG_RED_GREEN);
|
|
||||||
addEncodingSymbol("G/W", ManaImages.IMG_GREEN_WHITE);
|
|
||||||
addEncodingSymbol("W/B", ManaImages.IMG_WHITE_BLACK);
|
|
||||||
addEncodingSymbol("U/R", ManaImages.IMG_BLUE_RED);
|
|
||||||
addEncodingSymbol("B/G", ManaImages.IMG_BLACK_GREEN);
|
|
||||||
addEncodingSymbol("R/W", ManaImages.IMG_RED_WHITE);
|
|
||||||
addEncodingSymbol("G/U", ManaImages.IMG_GREEN_BLUE);
|
|
||||||
addEncodingSymbol("2/W", ManaImages.IMG_2W);
|
|
||||||
addEncodingSymbol("2/U", ManaImages.IMG_2U);
|
|
||||||
addEncodingSymbol("2/B", ManaImages.IMG_2B);
|
|
||||||
addEncodingSymbol("2/R", ManaImages.IMG_2R);
|
|
||||||
addEncodingSymbol("2/G", ManaImages.IMG_2G);
|
|
||||||
addEncodingSymbol("W/P", ManaImages.IMG_PHRYX_WHITE);
|
|
||||||
addEncodingSymbol("U/P", ManaImages.IMG_PHRYX_BLUE);
|
|
||||||
addEncodingSymbol("B/P", ManaImages.IMG_PHRYX_BLACK);
|
|
||||||
addEncodingSymbol("R/P", ManaImages.IMG_PHRYX_RED);
|
|
||||||
addEncodingSymbol("G/P", ManaImages.IMG_PHRYX_GREEN);
|
|
||||||
for (int i = 0; i <= 20; i++) {
|
|
||||||
addEncodingSymbol(String.valueOf(i), ColorlessManaImages.valueOf("IMG_" + i));
|
|
||||||
}
|
|
||||||
addEncodingSymbol("X", ColorlessManaImages.IMG_X);
|
|
||||||
addEncodingSymbol("Y", ColorlessManaImages.IMG_Y);
|
|
||||||
addEncodingSymbol("Z", ColorlessManaImages.IMG_Z);
|
|
||||||
addEncodingSymbol("C", GameplayImages.IMG_CHAOS);
|
|
||||||
addEncodingSymbol("Q", GameplayImages.IMG_UNTAP);
|
|
||||||
addEncodingSymbol("S", GameplayImages.IMG_SNOW);
|
|
||||||
addEncodingSymbol("T", GameplayImages.IMG_TAP);
|
|
||||||
|
|
||||||
// Set look and feel after skin loaded
|
|
||||||
FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Setting look and feel...");
|
|
||||||
ForgeLookAndFeel laf = new ForgeLookAndFeel();
|
|
||||||
laf.setForgeLookAndFeel(Singletons.getView().getFrame());
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Gets the name.
|
|
||||||
*
|
|
||||||
* @return Name of the current skin.
|
|
||||||
*//*
|
|
||||||
public static String getName() {
|
|
||||||
return FSkin.preferredName;
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Gets the skins.
|
|
||||||
*
|
|
||||||
* @return the skins
|
|
||||||
*//*
|
|
||||||
public static ArrayList<String> getSkinDirectoryNames() {
|
|
||||||
final ArrayList<String> mySkins = new ArrayList<String>();
|
|
||||||
|
|
||||||
final FileHandle dir;
|
|
||||||
if (Gdx.app.getType() == ApplicationType.Desktop) {
|
|
||||||
dir = Gdx.files.internal("./bin/" + FILE_SKINS_DIR); //needed to iterate over directory for Desktop
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dir = Gdx.files.internal(FILE_SKINS_DIR);
|
|
||||||
}
|
|
||||||
if (!dir.exists() || !dir.isDirectory()) {
|
|
||||||
System.err.println("FSkin > can't find skins directory!");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (FileHandle skinFile : dir.list()) {
|
|
||||||
String skinName = skinFile.name();
|
|
||||||
if (skinName.equalsIgnoreCase(".svn")) { continue; }
|
|
||||||
if (skinName.equalsIgnoreCase(".DS_Store")) { continue; }
|
|
||||||
mySkins.add(skinName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mySkins;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Iterable<String> getAllSkins() {
|
|
||||||
return allSkins;
|
|
||||||
}
|
|
||||||
|
|
||||||
*//** @return Map<Integer, Image> *//*
|
|
||||||
public static Map<Integer, SkinImage> getAvatars() {
|
|
||||||
return avatars;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isLoaded() { return loaded; }
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* <p>
|
|
||||||
* getColorFromPixel.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param {@link java.lang.Integer} pixel information
|
|
||||||
*//*
|
|
||||||
private static Color getColorFromPixel(final int pixel) {
|
|
||||||
int r, g, b, a;
|
|
||||||
a = (pixel >> 24) & 0x000000ff;
|
|
||||||
r = (pixel >> 16) & 0x000000ff;
|
|
||||||
g = (pixel >> 8) & 0x000000ff;
|
|
||||||
b = (pixel) & 0x000000ff;
|
|
||||||
return new Color(r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void assembleAvatars() {
|
|
||||||
FSkin.avatars = new HashMap<Integer, SkinImage>();
|
|
||||||
int counter = 0;
|
|
||||||
Color pxTest;
|
|
||||||
|
|
||||||
if (pxPreferredAvatars != null) {
|
|
||||||
final int pw = pxPreferredAvatars.getWidth();
|
|
||||||
final int ph = pxPreferredAvatars.getHeight();
|
|
||||||
|
|
||||||
for (int j = 0; j < ph; j += 100) {
|
|
||||||
for (int i = 0; i < pw; i += 100) {
|
|
||||||
if (i == 0 && j == 0) { continue; }
|
|
||||||
pxTest = FSkin.getColorFromPixel(pxPreferredAvatars.getPixel(i + 50, j + 50));
|
|
||||||
if (pxTest.getAlpha() == 0) { continue; }
|
|
||||||
FSkin.avatars.put(counter++, new SkinImage(new TextureRegion(txPreferredAvatars, i, j, 100, 100)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final int aw = pxDefaultAvatars.getWidth();
|
|
||||||
final int ah = pxDefaultAvatars.getHeight();
|
|
||||||
|
|
||||||
for (int j = 0; j < ah; j += 100) {
|
|
||||||
for (int i = 0; i < aw; i += 100) {
|
|
||||||
if (i == 0 && j == 0) { continue; }
|
|
||||||
pxTest = FSkin.getColorFromPixel(pxDefaultAvatars.getPixel(i + 50, j + 50));
|
|
||||||
if (pxTest.getAlpha() == 0) { continue; }
|
|
||||||
FSkin.avatars.put(counter++, new SkinImage(new TextureRegion(txDefaultAvatars, i, j, 100, 100)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setFoil(final SkinProp s0, boolean isOldStyle) {
|
|
||||||
int[] tempCoords = s0.getCoords();
|
|
||||||
int x0 = tempCoords[0];
|
|
||||||
int y0 = tempCoords[1];
|
|
||||||
int w0 = tempCoords[2];
|
|
||||||
int h0 = tempCoords[3];
|
|
||||||
|
|
||||||
SkinImage.setImage(s0, isOldStyle ? new TextureRegion(txOldFoils, x0, y0, w0, h0) : new TextureRegion(txFoils, x0, y0, w0, h0));
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user