Skip to content

Commit

Permalink
icons for item adjectives, closes #65
Browse files Browse the repository at this point in the history
more flexible auto image gen from spritesheets
  • Loading branch information
Grokmoo committed Oct 30, 2018
1 parent ccb9ddb commit 8474139
Show file tree
Hide file tree
Showing 15 changed files with 97 additions and 22 deletions.
1 change: 1 addition & 0 deletions data/item_adjectives/fine.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
id: fine
name: Fine
name_prefix: "Fine "
item_status_icon: gui/status_positive
value_modifier: 1.5
bonus_modifier: 1.1
penalty_modifier: 0.9
Expand Down
1 change: 1 addition & 0 deletions data/item_adjectives/rusty.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
id: rusty
name: Rusty
name_prefix: "Rusty "
item_status_icon: gui/status_negative
value_modifier: 0.5
bonus_modifier: 0.9
penalty_modifier: 1.1
Expand Down
1 change: 1 addition & 0 deletions data/item_adjectives/worn.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
id: worn
name: Worn
name_prefix: "Worn "
item_status_icon: gui/status_negative
value_modifier: 0.6
bonus_modifier: 0.9
penalty_modifier: 1.10
Expand Down
Binary file modified data/spritesheets/gui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions data/spritesheets/gui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,25 @@ groups:
hills02_disabled: [700, 216]
hills03_disabled: [800, 216]
swamp01_disabled: [900, 216]
status_icons:
size: [32, 32]
position: [1056, 960]
simple_image_gen_scale: 32
areas:
status_buff: [0, 0]
status_debuff: [32, 0]
status_earth: [64, 0]
status_fire: [96, 0]
status_heal: [128, 0]
status_ice: [160, 0]
status_electric: [192, 0]
status_shield: [0, 32]
status_acid: [32, 32]
status_water: [64, 32]
status_air: [96, 32]
status_darkness: [128, 32]
status_positive: [160, 32]
status_negative: [192, 32]
special:
areas:
empty: [0, 512, 5, 5]
Expand Down
9 changes: 9 additions & 0 deletions data/theme/widgets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ children:
foreground: "#icon#"
width_relative: Max
height_relative: Max
adjectives_pane:
preferred_size: [0, 4]
width_relative: ChildSum
x_relative: Max
layout: BoxHorizontal
children:
icon:
foreground: "#icon#"
preferred_size: [4, 4]
progress_bar:
background: bg_base
border: [1, 1, 1, 1]
Expand Down
1 change: 1 addition & 0 deletions docs/attribution.csv
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ data/spritesheets/gui.png,Cursors and simple UI elements,"0,512 to 384, 1024",Ja
data/spritesheets/gui.png,"Dark ""Gothic"" Style Elements","0,0 to 512, 512",Wyrmheart,CC0 - Public Domain,http://creativecommons.org/publicdomain/zero/1.0/,RPG Game UI,https://opengameart.org/content/rpg-game-ui,
data/spritesheets/gui.png,Menu Icons,"384, 512 to 1024,1024",Proprietary,GameDevMarket Pro,https://www.gamedevmarket.net/terms-conditions/#pro-licence,GUI Icons,https://www.gamedevmarket.net/asset/gui-icons-8656/,
data/spritesheets/gui.png,World Map Place Icons,"1022,513 to 2022,801",Battle for Wesnoth,GPL v2,https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html,Battle for Wesnoth various terrain images,https://www.wesnoth.org/,Desaturated for disabled versions
data/spritesheets/gui.png,Small Status Icons,"1056,960 to 1280,1024",OwlishMedia,CC0 - Public Domain,http://creativecommons.org/publicdomain/zero/1.0/,RPG UI Icons,https://opengameart.org/content/rpg-ui-icons,Rescaled some icons
data/spritesheets/creatures.png,player character sub-sprites,"0,0 to 1024,240",Battle for Wesnoth,GPL v2,https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html,Battle for Wesnoth various creature images,https://www.wesnoth.org/,All sprites heavily edited from unit sources
data/spritesheets/creatures.png,monsters,"0,336 to 352,432",Battle for Wesnoth,GPL v2,https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html,Battle for Wesnoth various creature images,https://www.wesnoth.org/,Some minor edits for uniformity
data/spritesheets/creatures.png,weapon sprites,"0,240 to 1024,336",Battle for Wesnoth,GPL v2,https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html,Battle for Wesnoth various creature images,https://www.wesnoth.org/,Sprites significantly edited from unit sources
Expand Down
11 changes: 11 additions & 0 deletions sulis_core/src/resource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use std::hash::Hash;
use std::fs;
use std::path::PathBuf;

use serde::{Deserialize, Deserializer, de::self};
use serde_yaml;

use config::Config;
Expand Down Expand Up @@ -278,3 +279,13 @@ pub fn subdirs<P: AsRef<Path>>(path: P) -> Result<Vec<PathBuf>, Error> {

Ok(result)
}

pub fn deserialize_image<'de, D>(deserializer: D) -> Result<Rc<Image>, D::Error>
where D: Deserializer<'de> {

let id = String::deserialize(deserializer)?;
match ResourceSet::get_image(&id) {
None => Err(de::Error::custom(format!("No image with ID '{}' found", id))),
Some(image) => Ok(image),
}
}
10 changes: 9 additions & 1 deletion sulis_core/src/resource/spritesheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,14 @@ impl Spritesheet {
}

let sprite = Rc::new(sprite);
if let Some(scale) = builder.simple_image_gen_scale {

// default to group scale, then fallback to overall sheet scale
// if neither are defined, don't gen images
let mut scale = group.simple_image_gen_scale;
if scale.is_none() {
scale = builder.simple_image_gen_scale;
}
if let Some(scale) = scale {
let scale = scale as i32;
let full_id = format!("{}/{}", builder.id, id);
let simple_image = SimpleImage {
Expand Down Expand Up @@ -228,6 +235,7 @@ struct SpritesheetGroup {
pub prefix: Option<String>,
pub areas: Option<HashMap<String, Vec<i32>>>,
pub from_template: Option<String>,
pub simple_image_gen_scale: Option<u32>,
}

impl SpritesheetGroup {
Expand Down
5 changes: 5 additions & 0 deletions sulis_module/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ impl Item {
})
}

pub fn adjective_icons(&self) -> Vec<String> {
self.builder_adjectives.iter().chain(self.added_adjectives.iter())
.map(|adj| adj.item_status_icon.id()).collect()
}

pub fn meets_prereqs(&self, actor: &Rc<Actor>) -> bool {
match self.prereqs {
None => true,
Expand Down
7 changes: 7 additions & 0 deletions sulis_module/src/item_adjective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Sulis. If not, see <http://www.gnu.org/licenses/>

use std::rc::Rc;

use sulis_core::resource::deserialize_image;
use sulis_core::image::Image;
use sulis_rules::{BonusList, AttackBonuses};

/// An adjective is a modifier that affects the stats of
Expand All @@ -25,6 +29,9 @@ pub struct ItemAdjective {
pub id: String,
pub name: String,

#[serde(deserialize_with = "deserialize_image")]
pub item_status_icon: Rc<Image>,

pub name_prefix: Option<String>,
pub name_postfix: Option<String>,
pub value_modifier: Option<f32>,
Expand Down
5 changes: 2 additions & 3 deletions sulis_view/src/inventory_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ impl WidgetKind for InventoryWindow {
button.borrow_mut().state.set_enabled(false);
Widget::add_child_to(&equipped_area, button);
}, Some(item_state) => {
let button = ItemButton::equipped(&self.entity, item_state.item.icon.id(),
*slot);
let button = ItemButton::equipped(&self.entity, &item_state.item, *slot);
if !combat_active {
let mut but = button.borrow_mut();
but.add_action("Unequip", unequip_item_cb(&self.entity, *slot));
Expand All @@ -118,7 +117,7 @@ impl WidgetKind for InventoryWindow {
Widget::add_child_to(&equipped_area, button);
}, Some(item_state) => {
let quantity = 1 + stash.borrow().items().get_quantity(&item_state);
let but = ItemButton::quick(&self.entity, quantity, item_state.item.icon.id(),
let but = ItemButton::quick(&self.entity, quantity, &item_state.item,
*quick_slot);

if actor.can_use_quick(*quick_slot) {
Expand Down
39 changes: 26 additions & 13 deletions sulis_view/src/item_button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use sulis_core::io::event;
use sulis_core::ui::{Callback, Widget, WidgetKind, WidgetState};
use sulis_rules::bonus::{AttackBuilder, AttackKindBuilder, Contingent};
use sulis_rules::{Bonus, BonusList, Armor, DamageKind, QuickSlot, Slot};
use sulis_module::{ability, item::{format_item_value, format_item_weight}, Module, PrereqList};
use sulis_module::{ability, Item, item::{format_item_value, format_item_weight}, Module, PrereqList};
use sulis_state::{EntityState, GameState, ItemState, inventory::has_proficiency};
use sulis_state::script::ScriptItemKind;
use sulis_widgets::{Label, TextArea};
Expand All @@ -39,6 +39,7 @@ enum Kind {

pub struct ItemButton {
icon: String,
adjective_icons: Vec<String>,
quantity: u32,
kind: Kind,
actions: Vec<(String, Callback)>,
Expand All @@ -49,37 +50,42 @@ pub struct ItemButton {
const ITEM_BUTTON_NAME: &str = "item_button";

impl ItemButton {
pub fn inventory(icon: String, quantity: u32, item_index: usize) -> Rc<RefCell<ItemButton>> {
ItemButton::new(icon, quantity, Kind::Inventory { item_index })
pub fn inventory(item: &Rc<Item>, quantity: u32,
item_index: usize) -> Rc<RefCell<ItemButton>> {
ItemButton::new(item, quantity, Kind::Inventory { item_index })
}

pub fn equipped(player: &Rc<RefCell<EntityState>>, icon: String,
pub fn equipped(player: &Rc<RefCell<EntityState>>, item: &Rc<Item>,
slot: Slot) -> Rc<RefCell<ItemButton>> {
let player = Rc::clone(player);
ItemButton::new(icon, 1, Kind::Equipped { player, slot })
ItemButton::new(item, 1, Kind::Equipped { player, slot })
}

pub fn quick(player: &Rc<RefCell<EntityState>>, quantity: u32, icon: String,
pub fn quick(player: &Rc<RefCell<EntityState>>, quantity: u32, item: &Rc<Item>,
quick: QuickSlot) -> Rc<RefCell<ItemButton>> {
let player = Rc::clone(player);
ItemButton::new(icon, quantity, Kind::Quick { player, quick })
ItemButton::new(item, quantity, Kind::Quick { player, quick })
}

pub fn prop(icon: String, quantity: u32, item_index: usize,
pub fn prop(item: &Rc<Item>, quantity: u32, item_index: usize,
prop_index: usize) -> Rc<RefCell<ItemButton>> {
ItemButton::new(icon, quantity,
ItemButton::new(item, quantity,
Kind::Prop { prop_index, item_index })
}

pub fn merchant(icon: String, quantity: u32, item_index: usize,
pub fn merchant(item: &Rc<Item>, quantity: u32, item_index: usize,
merchant_id: &str) -> Rc<RefCell<ItemButton>> {
ItemButton::new(icon, quantity,
ItemButton::new(item, quantity,
Kind::Merchant { id: merchant_id.to_string(), item_index })
}

fn new(icon: String, quantity: u32, kind: Kind) -> Rc<RefCell<ItemButton>> {
fn new(item: &Rc<Item>, quantity: u32, kind: Kind) -> Rc<RefCell<ItemButton>> {
let icon = item.icon.id();
let adjective_icons = item.adjective_icons();

Rc::new(RefCell::new(ItemButton {
icon,
adjective_icons,
quantity,
kind,
actions: Vec::new(),
Expand Down Expand Up @@ -211,7 +217,14 @@ impl WidgetKind for ItemButton {
let icon = Widget::empty("icon");
icon.borrow_mut().state.add_text_arg("icon", &self.icon);

vec![icon, qty_label]
let adj = Widget::empty("adjectives_pane");
for icon in self.adjective_icons.iter() {
let widget = Widget::empty("icon");
widget.borrow_mut().state.add_text_arg("icon", icon);
Widget::add_child_to(&adj, widget);
}

vec![icon, adj, qty_label]
}

fn on_mouse_enter(&mut self, widget: &Rc<RefCell<Widget>>) -> bool {
Expand Down
8 changes: 4 additions & 4 deletions sulis_view/src/item_list_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl ItemListPane {
for (index, &(qty, ref item)) in merchant.items().iter().enumerate() {
if !self.cur_filter.get().is_allowed(&item.item) { continue; }

let item_button = ItemButton::merchant(item.item.icon.id(), qty, index, merchant_id);
let item_button = ItemButton::merchant(&item.item, qty, index, merchant_id);
item_button.borrow_mut().add_action("Buy", buy_item_cb(merchant_id, index));

scrollpane.borrow().add_to_content(Widget::with_defaults(item_button));
Expand All @@ -130,7 +130,7 @@ impl ItemListPane {
for (index, &(qty, ref item)) in items.iter().enumerate() {
if !self.cur_filter.get().is_allowed(&item.item) { continue; }

let item_button = ItemButton::prop(item.item.icon.id(), qty, index, prop_index);
let item_button = ItemButton::prop(&item.item, qty, index, prop_index);
if !combat_active {
item_button.borrow_mut()
.add_action("Take", take_item_cb(prop_index, index));
Expand All @@ -156,7 +156,7 @@ impl ItemListPane {
for (index, &(quantity, ref item)) in stash.items().iter().enumerate() {
if !self.cur_filter.get().is_allowed(&item.item) { continue; }

let item_but = ItemButton::inventory(item.item.icon.id(), quantity, index);
let item_but = ItemButton::inventory(&item.item, quantity, index);

if let Some(ref usable) = item.item.usable {
if !combat_active && item.item.meets_prereqs(&actor.actor) {
Expand Down Expand Up @@ -212,7 +212,7 @@ impl WidgetKind for ItemListPane {
};
let amount = GameState::party_coins() as f32 /
Module::rules().item_value_display_factor;
let button = ItemButton::inventory(coins_item.icon.id(), amount as u32, 0);
let button = ItemButton::inventory(&coins_item, amount as u32, 0);
let coins_button = Widget::with_theme(button, "coins_button");
coins_button.borrow_mut().state.set_enabled(false);
children.push(coins_button);
Expand Down
2 changes: 1 addition & 1 deletion sulis_view/src/quick_item_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn create_button(entity: &Rc<RefCell<EntityState>>, slot: QuickSlot,
}, Some(item_state) => {
let quantity = 1 + stash.borrow().items().get_quantity(&item_state);
let kind = ScriptItemKind::Quick(slot);
let button = ItemButton::quick(entity, quantity, item_state.item.icon.id(), slot);
let button = ItemButton::quick(entity, quantity, &item_state.item, slot);
button.borrow_mut().add_action("Use", use_item_cb(entity, kind));
button.borrow_mut().add_action("Clear Slot", clear_quickslot_cb(entity, slot));
let widget = Widget::with_theme(button.clone(), theme_id);
Expand Down

0 comments on commit 8474139

Please sign in to comment.