use std::rc::Rc;
use sc2_proto::{debug, raw, sc2api};
use super::super::{FromProto, IntoProto, Result};
use data::{Ability, Color, Point2, Point3, Tag, Unit};
#[derive(Debug, Copy, Clone)]
pub enum ActionTarget {
Unit(Tag),
Location(Point2),
}
#[derive(Debug, Clone)]
pub struct Action {
ability: Ability,
units: Vec<Tag>,
target: Option<ActionTarget>,
}
impl Action {
pub fn new(ability: Ability) -> Self {
Self {
ability: ability,
units: vec![],
target: None,
}
}
pub fn units<'a, T>(self, units: T) -> Self
where
T: Iterator<Item = &'a Rc<Unit>>,
{
Self {
units: units.map(|u| u.get_tag()).collect(),
..self
}
}
pub fn unit_tags(self, units: Vec<Tag>) -> Self {
Self {
units: units,
..self
}
}
pub fn target(self, target: ActionTarget) -> Self {
Self {
target: Some(target),
..self
}
}
}
impl FromProto<raw::ActionRawUnitCommand> for Action {
fn from_proto(action: raw::ActionRawUnitCommand) -> Result<Self> {
Ok(Self {
ability: Ability::from_proto(action.get_ability_id() as u32)?,
units: {
let mut unit_tags = vec![];
for tag in action.get_unit_tags() {
unit_tags.push(*tag);
}
unit_tags
},
target: {
if action.has_target_unit_tag() {
Some(ActionTarget::Unit(action.get_target_unit_tag()))
} else if action.has_target_world_space_pos() {
let pos = action.get_target_world_space_pos();
Some(ActionTarget::Location(Point2::new(
pos.get_x(),
pos.get_y(),
)))
} else {
None
}
},
})
}
}
impl IntoProto<sc2api::Action> for Action {
fn into_proto(self) -> Result<sc2api::Action> {
let mut action = sc2api::Action::new();
{
let cmd = action.mut_action_raw().mut_unit_command();
cmd.set_ability_id(self.ability.into_proto()? as i32);
match self.target {
Some(ActionTarget::Unit(tag)) => {
cmd.set_target_unit_tag(tag);
},
Some(ActionTarget::Location(pos)) => {
let target = cmd.mut_target_world_space_pos();
target.set_x(pos.x);
target.set_y(pos.y);
},
None => (),
}
for tag in self.units {
cmd.mut_unit_tags().push(tag);
}
}
Ok(action)
}
}
#[derive(Debug, Copy, Clone)]
pub enum DebugTextTarget {
Screen(Point2),
World(Point3),
}
#[derive(Debug, Clone)]
pub struct DebugText {
text: String,
target: Option<DebugTextTarget>,
color: Color,
}
impl DebugText {
pub fn new(text: String) -> Self {
Self {
text: text,
target: None,
color: (0xFF, 0xFF, 0xFF),
}
}
pub fn target(self, target: DebugTextTarget) -> Self {
Self {
target: Some(target),
..self
}
}
pub fn color(self, color: Color) -> Self {
Self {
color: color,
..self
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct DebugLine {
p1: Point3,
p2: Point3,
color: Color,
}
impl DebugLine {
pub fn new(p1: Point3, p2: Point3) -> Self {
Self {
p1: p1,
p2: p2,
color: (0xFF, 0xFF, 0xFF),
}
}
pub fn color(self, color: Color) -> Self {
Self {
color: color,
..self
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct DebugAabb {
min: Point3,
max: Point3,
color: Color,
}
impl DebugAabb {
pub fn new(min: Point3, max: Point3) -> Self {
Self {
min: min,
max: max,
color: (0xFF, 0xFF, 0xFF),
}
}
pub fn color(self, color: Color) -> Self {
Self {
color: color,
..self
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct DebugSphere {
center: Point3,
radius: f32,
color: Color,
}
impl DebugSphere {
pub fn new(center: Point3, radius: f32) -> Self {
Self {
center: center,
radius: radius,
color: (0xFF, 0xFF, 0xFF),
}
}
pub fn color(self, color: Color) -> Self {
Self {
color: color,
..self
}
}
}
#[derive(Debug, Clone)]
pub enum DebugCommand {
Text(DebugText),
Line(DebugLine),
Aabb(DebugAabb),
Sphere(DebugSphere),
}
impl From<DebugText> for DebugCommand {
fn from(text: DebugText) -> Self {
DebugCommand::Text(text)
}
}
impl From<DebugLine> for DebugCommand {
fn from(line: DebugLine) -> Self {
DebugCommand::Line(line)
}
}
impl From<DebugAabb> for DebugCommand {
fn from(aabb: DebugAabb) -> Self {
DebugCommand::Aabb(aabb)
}
}
impl From<DebugSphere> for DebugCommand {
fn from(sphere: DebugSphere) -> Self {
DebugCommand::Sphere(sphere)
}
}
impl IntoProto<debug::DebugCommand> for DebugCommand {
fn into_proto(self) -> Result<debug::DebugCommand> {
match self {
DebugCommand::Text(DebugText {
text,
target,
color,
}) => {
let mut cmd = debug::DebugCommand::new();
let mut debug_text = debug::DebugText::new();
debug_text.set_text(text);
match target {
Some(DebugTextTarget::Screen(p)) => {
debug_text.mut_virtual_pos().set_x(p.x);
debug_text.mut_virtual_pos().set_y(p.y);
},
Some(DebugTextTarget::World(p)) => {
debug_text.mut_world_pos().set_x(p.x);
debug_text.mut_world_pos().set_y(p.y);
debug_text.mut_world_pos().set_z(p.z);
},
None => (),
}
debug_text.mut_color().set_r(color.0 as u32);
debug_text.mut_color().set_g(color.1 as u32);
debug_text.mut_color().set_b(color.2 as u32);
cmd.mut_draw().mut_text().push(debug_text);
Ok(cmd)
},
DebugCommand::Line(DebugLine { p1, p2, color }) => {
let mut cmd = debug::DebugCommand::new();
let mut debug_line = debug::DebugLine::new();
debug_line.mut_line().mut_p0().set_x(p1.x);
debug_line.mut_line().mut_p0().set_y(p1.y);
debug_line.mut_line().mut_p0().set_z(p1.z);
debug_line.mut_line().mut_p1().set_x(p2.x);
debug_line.mut_line().mut_p1().set_y(p2.y);
debug_line.mut_line().mut_p1().set_z(p2.z);
debug_line.mut_color().set_r(color.0 as u32);
debug_line.mut_color().set_g(color.1 as u32);
debug_line.mut_color().set_b(color.2 as u32);
cmd.mut_draw().mut_lines().push(debug_line);
Ok(cmd)
},
DebugCommand::Aabb(DebugAabb { min, max, color }) => {
let mut cmd = debug::DebugCommand::new();
let mut debug_box = debug::DebugBox::new();
debug_box.mut_min().set_x(min.x);
debug_box.mut_min().set_y(min.y);
debug_box.mut_min().set_z(min.z);
debug_box.mut_max().set_x(max.x);
debug_box.mut_max().set_y(max.y);
debug_box.mut_max().set_z(max.z);
debug_box.mut_color().set_r(color.0 as u32);
debug_box.mut_color().set_g(color.1 as u32);
debug_box.mut_color().set_b(color.2 as u32);
cmd.mut_draw().mut_boxes().push(debug_box);
Ok(cmd)
},
DebugCommand::Sphere(DebugSphere {
center,
radius,
color,
}) => {
let mut cmd = debug::DebugCommand::new();
let mut debug_sphere = debug::DebugSphere::new();
debug_sphere.mut_p().set_x(center.x);
debug_sphere.mut_p().set_y(center.y);
debug_sphere.mut_p().set_z(center.z);
debug_sphere.set_r(radius);
debug_sphere.mut_color().set_r(color.0 as u32);
debug_sphere.mut_color().set_g(color.1 as u32);
debug_sphere.mut_color().set_b(color.2 as u32);
cmd.mut_draw().mut_spheres().push(debug_sphere);
Ok(cmd)
},
}
}
}