Skip to content

Commit

Permalink
[#72] Shirts (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
Orchaldir authored Sep 21, 2023
1 parent bfbbe89 commit 861ce4a
Show file tree
Hide file tree
Showing 19 changed files with 341 additions and 84 deletions.
18 changes: 17 additions & 1 deletion resources/characters/characters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
pants:
style: Regular
color: Blue
shirt:
sleeve_style: Long
neckline: Crew
color: White
head:
ears:
type: Normal
Expand Down Expand Up @@ -164,6 +168,10 @@
pants:
style: Balloon
color: Red
shirt:
sleeve_style: Long
neckline: DeepV
color: Red
head:
ears:
type: Normal
Expand Down Expand Up @@ -221,7 +229,11 @@
clothing:
type: Simple
pants:
style: Regular
style: Shorts
color: Purple
shirt:
sleeve_style: None
neckline: Crew
color: Purple
head:
ears:
Expand Down Expand Up @@ -270,6 +282,10 @@
pants:
style: Regular
color: Gray
shirt:
sleeve_style: Short
neckline: Crew
color: Gray
head:
ears:
type: Normal
Expand Down
14 changes: 14 additions & 0 deletions resources/templates/appearance_edit.html.tera
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,20 @@
</li>
</ul>
</li>
<li>
<b>Shirt</b>
<ul>
<li>
<b>Sleeve Style:</b> {{ macros::add_select(name="appearance.body.clothing.shirt.sleeve_style", options=[ "Long","None","Short" ], selected=appearance.body.clothing.shirt.sleeve_style, update=true) }}
</li>
<li>
<b>Neckline:</b> {{ macros::add_select(name="appearance.body.clothing.shirt.neckline", options=[ "Boat","Crew","DeepV","None","Scoop","V" ], selected=appearance.body.clothing.shirt.neckline, update=true) }}
</li>
<li>
<b>Color:</b> {{ macros::add_select(name="appearance.body.clothing.shirt.color", options=[ "Aqua","Black","Blue","Fuchsia","Gray","Green","Lime","Maroon","Navy","Olive","Orange","Purple","Red","SaddleBrown","Silver","Teal","White","Yellow" ], selected=appearance.body.clothing.shirt.color, update=true) }}
</li>
</ul>
</li>
{% endif %}
</ul>
</li>
Expand Down
14 changes: 14 additions & 0 deletions resources/templates/character.html.tera
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,20 @@
</li>
</ul>
</li>
<li>
<b>Shirt</b>
<ul>
<li>
<b>Sleeve Style:</b> {{ appearance.body.clothing.shirt.sleeve_style }}
</li>
<li>
<b>Neckline:</b> {{ appearance.body.clothing.shirt.neckline }}
</li>
<li>
<b>Color:</b> {{ appearance.body.clothing.shirt.color }}
</li>
</ul>
</li>
{% endif %}
</ul>
</li>
Expand Down
3 changes: 3 additions & 0 deletions rpg_tools_core/src/model/equipment/appearance/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::model::equipment::appearance::pants::Pants;
use crate::model::equipment::appearance::shirt::Shirt;
use macro_ui::ui;
use serde::{Deserialize, Serialize};

pub mod pants;
pub mod shirt;

#[derive(ui, Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type")]
Expand All @@ -11,5 +13,6 @@ pub enum Clothing {
None,
Simple {
pants: Pants,
shirt: Shirt,
},
}
4 changes: 2 additions & 2 deletions rpg_tools_core/src/model/equipment/appearance/pants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use macro_convert::Convert;
use macro_ui::ui;
use serde::{Deserialize, Serialize};

/// Clothing for the lower body.
/// The pants of the [`character`](crate::model::character::Character).
#[derive(ui, Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Pants {
pub style: PantsStyle,
pub color: Color,
}

/// What style of pants?
/// What style of [`pants`](Pants)?
#[derive(Convert, ui, Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum PantsStyle {
Balloon,
Expand Down
33 changes: 33 additions & 0 deletions rpg_tools_core/src/model/equipment/appearance/shirt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::model::color::Color;
use macro_convert::Convert;
use macro_ui::ui;
use serde::{Deserialize, Serialize};

/// The shirt of the [`character`](crate::model::character::Character).
#[derive(ui, Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Shirt {
pub sleeve_style: SleeveStyle,
pub neckline: Neckline,
pub color: Color,
}

/// What style of neckline?
#[derive(Convert, ui, Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum Neckline {
Boat,
Crew,
DeepV,
#[default]
None,
Scoop,
V,
}

/// What style of sleeves?
#[derive(Convert, ui, Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum SleeveStyle {
#[default]
Long,
None,
Short,
}
11 changes: 6 additions & 5 deletions rpg_tools_rendering/examples/pants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ extern crate rpg_tools_rendering;

use crate::utils::render::render_2_sets;
use rpg_tools_core::model::character::appearance::body::{Body, BodyShape};
use rpg_tools_core::model::character::appearance::head::Head;
use rpg_tools_core::model::character::appearance::Appearance;
use rpg_tools_core::model::color::Color;
use rpg_tools_core::model::equipment::appearance::pants::{Pants, PantsStyle};
use rpg_tools_core::model::equipment::appearance::Clothing;
use rpg_tools_core::model::length::Length;
use rpg_tools_core::model::width::Width;

pub mod utils;

Expand Down Expand Up @@ -40,11 +38,14 @@ fn create_appearance(height: Length, pants: &Pants, shape: &BodyShape) -> Appear
Appearance::humanoid(
Body {
shape: *shape,
width: Width::default(),
width: Default::default(),
skin: Default::default(),
clothing: Clothing::Simple { pants: *pants },
clothing: Clothing::Simple {
pants: *pants,
shirt: Default::default(),
},
},
Head::default(),
Default::default(),
height,
)
}
50 changes: 50 additions & 0 deletions rpg_tools_rendering/examples/shirts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
extern crate rpg_tools_core;
extern crate rpg_tools_rendering;

use crate::utils::render::render_2_sets;
use rpg_tools_core::model::character::appearance::body::{Body, BodyShape};
use rpg_tools_core::model::character::appearance::Appearance;
use rpg_tools_core::model::color::Color;
use rpg_tools_core::model::equipment::appearance::shirt::{Neckline, Shirt, SleeveStyle};
use rpg_tools_core::model::equipment::appearance::Clothing;
use rpg_tools_core::model::length::Length;

pub mod utils;

fn main() {
let mut shirts = vec![];

for neckline in Neckline::get_all() {
for sleeve_style in SleeveStyle::get_all() {
shirts.push(Shirt {
sleeve_style,
neckline,
color: Color::Aqua,
})
}
}

render_2_sets(
"shirts.svg",
shirts,
BodyShape::get_all(),
create_appearance,
false,
);
}

fn create_appearance(height: Length, shirt: &Shirt, shape: &BodyShape) -> Appearance {
Appearance::humanoid(
Body {
shape: *shape,
width: Default::default(),
skin: Default::default(),
clothing: Clothing::Simple {
pants: Default::default(),
shirt: *shirt,
},
},
Default::default(),
height,
)
}
82 changes: 40 additions & 42 deletions rpg_tools_rendering/src/rendering/body/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::math::aabb2d::{get_end_x, get_start_x, AABB};
use crate::math::orientation::Orientation;
use crate::math::point2d::Point2d;
use crate::math::polygon2d::Polygon2d;
use crate::math::polygon2d::builder::Polygon2dBuilder;
use crate::math::size2d::Size2d;
use crate::renderer::{RenderOptions, Renderer};
use crate::rendering::body::torso::render_torso;
use crate::rendering::config::RenderConfig;
use crate::rendering::equipment::pants::interpolate;
use rpg_tools_core::model::character::appearance::body::Body;
use std::ops::Mul;

Expand All @@ -15,8 +16,7 @@ pub fn render_body(renderer: &mut dyn Renderer, config: &RenderConfig, aabb: &AA
let options = config.get_skin_options(&body.skin);

render_legs(renderer, config, aabb, body, &options);
render_arms(renderer, config, &aabb, body, &options);
render_hands(renderer, config, aabb, body, &options);
render_arms(renderer, config, aabb, body, &options);
render_torso(renderer, config, aabb, body, &options);
}

Expand Down Expand Up @@ -50,67 +50,65 @@ fn render_legs(
renderer.render_circle_arc(&right_foot_start, foot_radius, offset, angle, options);
}

fn render_hands(
renderer: &mut dyn Renderer,
config: &RenderConfig,
aabb: &AABB,
body: &Body,
options: &RenderOptions,
) {
pub fn render_hands(renderer: &mut dyn Renderer, config: &RenderConfig, aabb: &AABB, body: &Body) {
let options = config.get_skin_options(&body.skin);
let hand_radius = config.body.get_hand_radius(body, aabb);
let distance_between_hands = config.body.get_shoulder_width(body)
+ config.body.get_arm_width(body)
+ config.body.get_fat_offset_factor(body);
let distance_between_hands =
config.body.get_distance_between_hands(body) + config.body.get_hand_radius_factor(body);
let hand_y = config.body.get_arm_y() + config.body.height_arm;
let (left_hand_center, right_hand_center) =
aabb.get_mirrored_points(distance_between_hands, hand_y);

renderer.render_circle(&left_hand_center, hand_radius, options);
renderer.render_circle(&right_hand_center, hand_radius, options);
renderer.render_circle(&left_hand_center, hand_radius, &options);
renderer.render_circle(&right_hand_center, hand_radius, &options);
}

fn render_arms(
renderer: &mut dyn Renderer,
config: &RenderConfig,
aabb: &&AABB,
aabb: &AABB,
body: &Body,
options: &RenderOptions,
) {
let arm_size = aabb
.size()
.scale(config.body.get_arm_width(body), config.body.height_arm);
let arm_start_x = get_start_x(config.body.get_shoulder_width(body));
let right_arm_start = aabb.get_point(
arm_start_x - config.body.get_arm_width(body),
config.body.get_arm_y(),
);
let fat_offset = aabb.convert_to_height(config.body.get_fat_offset_factor(body) / 2.0);
let polygon = create_arm(arm_size, right_arm_start, fat_offset as i32);
let polygon = get_left_arm(config, aabb, body).build();

renderer.render_rounded_polygon(&polygon, options);
renderer.render_rounded_polygon(&aabb.mirrored(&polygon), options);
}

fn create_arm(arm_size: Size2d, right_arm_start: Point2d, offset: i32) -> Polygon2d {
let right_arm = AABB::new(right_arm_start, arm_size);
let mut polygon: Polygon2d = (&right_arm).into();

if offset != 0 {
let corners = polygon.corners_mut();

update_corner(corners, 2, offset);
update_corner(corners, 3, offset);
}
pub fn get_left_arm(config: &RenderConfig, aabb: &AABB, body: &Body) -> Polygon2dBuilder {
let mut builder = get_left_arm_short(config, aabb, body, false);
let width = config.body.get_arm_width(body);
let bottom_x = get_end_x(config.body.get_distance_between_hands(body));
let y = config.body.get_arm_y() + config.body.height_arm;

polygon.create_sharp_corner(1);
builder.add_point(aabb.get_point(bottom_x, y), false);
builder.add_point_cw(aabb.get_point(bottom_x + width, y), false);

polygon
builder
}

fn update_corner(corners: &mut [Point2d], index: usize, offset: i32) {
if let Some(p) = corners.get_mut(index) {
p.x -= offset;
}
pub fn get_left_arm_short(
config: &RenderConfig,
aabb: &AABB,
body: &Body,
bottom_sharp: bool,
) -> Polygon2dBuilder {
let mut builder = Polygon2dBuilder::new();
let width = config.body.get_arm_width(body);
let top_x = get_end_x(config.body.get_shoulder_width(body) * 0.94);
let bottom_x = get_end_x(config.body.get_distance_between_hands(body));
let bottom_x = interpolate(top_x, bottom_x, 0.7);
let y = config.body.get_arm_y();
let mid_y = y + 0.2;

builder.add_point(aabb.get_point(top_x, y), true);
builder.add_point_cw(aabb.get_point(top_x + width, y), false);
builder.add_point(aabb.get_point(top_x, y + 0.1), true);
builder.add_point(aabb.get_point(bottom_x, mid_y), bottom_sharp);
builder.add_point_cw(aabb.get_point(bottom_x + width, mid_y), bottom_sharp);

builder
}

fn render_leg(renderer: &mut dyn Renderer, options: &RenderOptions, start: Point2d, size: Size2d) {
Expand Down
Loading

0 comments on commit 861ce4a

Please sign in to comment.