Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Adjust some structures. #16

Merged
merged 2 commits into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions plugins/random/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![feature(once_cell)]

use ayaka_bindings::*;
use log::error;
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::sync::{LazyLock, Mutex};

Expand All @@ -22,7 +21,7 @@ fn rnd(args: Vec<RawValue>) -> RawValue {
};
RawValue::Num(res)
} else {
error!("Cannot get random engine.");
log::error!("Cannot get random engine.");
RawValue::Unit
}
}
141 changes: 141 additions & 0 deletions utils/ayaka-bindings-types/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use ayaka_script::RawValue;
use fallback::FallbackSpec;
use serde::{Deserialize, Serialize};
use std::{
borrow::Cow,
collections::{HashMap, VecDeque},
};

/// The unit of one line in an action.
///
/// If a frontend supports animation,
/// the characters in [`ActionLine::Chars`] should be printed one by one,
/// while the characters in [`ActionLine::Block`] should be printed together.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", content = "data")]
pub enum ActionSubText {
/// Characters printed one by one.
/// Usually they are meaningful texts.
Chars(String),
/// Characters printed together.
/// Usually they are HTML tags or other control characters.
Block(String),
}

impl ActionSubText {
/// Creates [`ActionLine::Chars`].
pub fn chars(s: impl Into<String>) -> Self {
Self::Chars(s.into())
}

/// Creates [`ActionLine::Block`].
pub fn block(s: impl Into<String>) -> Self {
Self::Block(s.into())
}

/// Gets a reference of [`str`].
pub fn as_str(&self) -> &str {
match self {
Self::Chars(s) | Self::Block(s) => s,
}
}

/// Gets the inner [`String`].
pub fn into_string(self) -> String {
match self {
Self::Chars(s) | Self::Block(s) => s,
}
}
}

/// A map from variable name to [`RawValue`].
pub type VarMap = HashMap<String, RawValue>;

/// The serializable context.
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct RawContext {
/// Current base paragraph tag.
pub cur_base_para: String,
/// Current paragraph tag.
pub cur_para: String,
/// Current text index.
pub cur_act: usize,
/// Current local variables.
pub locals: VarMap,
}

/// The `text` is a [`VecDeque<ActionSubText>`].
/// The [`ActionSubText`] could be pushed and poped at front or back.
///
/// Generally, you should avoid using `push_back` directly.
/// To reduce allocations in serialization, you should use
/// `push_back_chars` and `push_back_block`.
///
/// ```
/// # use ayaka_bindings_types::*;
/// let mut text = ActionText::default();
/// text.push_back_chars("Hello ");
/// assert_eq!(text.text[0], ActionSubText::chars("Hello "));
/// text.push_back_chars("world!");
/// assert_eq!(text.text[0], ActionSubText::chars("Hello world!"));
/// ```
#[derive(Debug, Default, Clone, Serialize, Deserialize, FallbackSpec)]
pub struct ActionText {
/// The full texts.
pub text: VecDeque<ActionSubText>,
/// The key of current character.
pub ch_key: Option<String>,
/// The current character.
pub character: Option<String>,
/// The temp variables.
pub vars: VarMap,
}

impl ActionText {
/// Push the string as [`ActionLine::Chars`] to the back.
/// If the back element is also [`ActionLine::Chars`], the string is appended.
pub fn push_back_chars<'a>(&mut self, s: impl Into<Cow<'a, str>>) {
let s = s.into();
if let Some(ActionSubText::Chars(text)) = self.text.back_mut() {
text.push_str(&s);
} else {
self.text.push_back(ActionSubText::chars(s));
}
}

/// Push the string as [`ActionLine::Block`] to the back.
/// If the back element is also [`ActionLine::Block`], the string is appended.
pub fn push_back_block<'a>(&mut self, s: impl Into<Cow<'a, str>>) {
let s = s.into();
if let Some(ActionSubText::Block(text)) = self.text.back_mut() {
text.push_str(&s);
} else {
self.text.push_back(ActionSubText::block(s));
}
}
}

/// The full action information in one line of config.
/// It provides the full texts and other properties exacted from [`ayaka_script::Text`].
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "data")]
pub enum Action {
/// An empty action usually means an `exec` or custom action.
#[default]
Empty,
/// A text action, display some texts.
Text(ActionText),
/// A switch action, display switches and let player to choose.
Switches(Vec<Switch>),
/// A custom action.
Custom(VarMap),
}

/// One switch in the switches of an [`Action`].
#[derive(Debug, Default, Clone, Serialize, Deserialize, FallbackSpec)]
pub struct Switch {
/// The switch text.
pub text: String,
/// Whether the switch is enabled.
pub enabled: bool,
}
Loading