initial commit
This commit is contained in:
commit
065844a66b
15 changed files with 9722 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
2037
Cargo.lock
generated
Normal file
2037
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
4
Cargo.toml
Normal file
4
Cargo.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
[workspace]
|
||||
resolver = "3"
|
||||
members = [ "core","gui"]
|
||||
|
16
core/Cargo.toml
Normal file
16
core/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
name = "core"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
confique = { version = "0.3.0", features = ["toml"] }
|
||||
derive_more = { version = "2.0.1", features = ["display", "from_str"] }
|
||||
directories = "6.0.0"
|
||||
serde = "1.0.219"
|
||||
toml = "0.8.23"
|
||||
unity_release_api = { git = "https://git.kitsu.cafe/rowan/unity-release-client.git", version = "0.1.0" }
|
||||
osstr_traits = { path = "../../osstr_traits/crates/osstr_traits", version = "0.1.0" }
|
||||
osstr_traits_derive = { path = "../../osstr_traits/crates/osstr_traits_derive", version = "0.1.0" }
|
||||
#osstr_traits = { git = "https://git.kitsu.cafe/rowan/osstr-traits.git", version = "0.1.0" }
|
||||
#osstr_traits_derive = { git = "https://git.kitsu.cafe/rowan/osstr-traits.git", version = "0.1.0" }
|
6355
core/blah.rs
Normal file
6355
core/blah.rs
Normal file
File diff suppressed because it is too large
Load diff
170
core/src/collection.rs
Normal file
170
core/src/collection.rs
Normal file
|
@ -0,0 +1,170 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
ffi::{OsStr, OsString},
|
||||
fmt::Display,
|
||||
ops::{Deref, DerefMut},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use derive_more::Display;
|
||||
use osstr_traits::{OsDisplay, ToOsString};
|
||||
|
||||
type OsStrDisplay<'a> = std::ffi::os_str::Display<'a>;
|
||||
type PathDisplay<'a> = std::path::Display<'a>;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct DelimitedVec<T, const D: char = ' '>(Vec<T>);
|
||||
|
||||
impl<T: OsDisplay, const D: char> OsDisplay for DelimitedVec<T, D> {
|
||||
fn fmt_os(&self, f: &mut osstr_traits::OsStringFormatter) -> std::fmt::Result {
|
||||
let mut first = true;
|
||||
|
||||
for item in &self.0 {
|
||||
if !first {
|
||||
f.write_os_str(&D.to_os_string())?;
|
||||
}
|
||||
|
||||
item.fmt_os(f)?;
|
||||
first = false;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display, const D: char> Display for DelimitedVec<T, D> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut first = true;
|
||||
|
||||
for item in &self.0 {
|
||||
if !first {
|
||||
write!(f, "{D}")?;
|
||||
}
|
||||
|
||||
write!(f, "{item}")?;
|
||||
first = false;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, const D: char> FromIterator<A> for DelimitedVec<A, D> {
|
||||
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
|
||||
Self(iter.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const D: char> From<&'a Vec<PathBuf>> for DelimitedVec<PathDisplay<'a>, D> {
|
||||
fn from(value: &'a Vec<PathBuf>) -> Self {
|
||||
let iter = value.iter().map(|s| s.display());
|
||||
Self::from_iter(iter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, const D: char> From<&'a Vec<OsString>> for DelimitedVec<OsStrDisplay<'a>, D> {
|
||||
fn from(value: &'a Vec<OsString>) -> Self {
|
||||
let iter = value.iter().map(|s| s.display());
|
||||
Self::from_iter(iter)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct CommandArgs<T>(pub Vec<T>);
|
||||
|
||||
impl<T: OsDisplay> OsDisplay for CommandArgs<T> {
|
||||
fn fmt_os(&self, f: &mut osstr_traits::OsStringFormatter) -> std::fmt::Result {
|
||||
let mut first = true;
|
||||
|
||||
for item in &self.0 {
|
||||
if !first {
|
||||
f.write_os_str(OsStr::new(" "))?;
|
||||
}
|
||||
|
||||
item.fmt_os(f)?;
|
||||
first = false;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display> Display for CommandArgs<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut first = true;
|
||||
|
||||
for item in &self.0 {
|
||||
if !first {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
|
||||
write!(f, "{item}")?;
|
||||
first = false;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for CommandArgs<T> {
|
||||
fn default() -> Self {
|
||||
Self(Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for CommandArgs<T> {
|
||||
type Target = Vec<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for CommandArgs<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> FromIterator<A> for CommandArgs<A> {
|
||||
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
|
||||
Self(iter.into_iter().collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for CommandArgs<T> {
|
||||
type Item = T;
|
||||
type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display)]
|
||||
#[display("{} {}", command.display(), args)]
|
||||
pub struct Command<'a, T> {
|
||||
command: Cow<'a, OsStr>,
|
||||
args: CommandArgs<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> Command<'a, T> {
|
||||
pub fn new(command: impl Into<Cow<'a, OsStr>>) -> Self {
|
||||
Self {
|
||||
command: command.into(),
|
||||
args: CommandArgs::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: T) {
|
||||
self.args.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: AsRef<OsStr>> Command<'a, T> {
|
||||
pub fn into_os_command(self) -> std::process::Command {
|
||||
let mut cmd = std::process::Command::new(self.command);
|
||||
cmd.args(self.args);
|
||||
cmd
|
||||
}
|
||||
}
|
108
core/src/config.rs
Normal file
108
core/src/config.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
env,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use confique::Config;
|
||||
use directories::ProjectDirs;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::error::{Error, ShellExpansionError};
|
||||
|
||||
trait Fallback: Config {
|
||||
fn fallback() -> <Self as Config>::Partial;
|
||||
}
|
||||
|
||||
fn project_dir() -> Option<ProjectDirs> {
|
||||
ProjectDirs::from("cafe", "kitsu", "TormentNexus")
|
||||
}
|
||||
|
||||
fn expand_tilde<'a>(path: impl Into<Cow<'a, Path>>) -> Result<Cow<'a, Path>, ShellExpansionError> {
|
||||
let path = path.into();
|
||||
let into_err = || ShellExpansionError::new("~", path.to_str());
|
||||
|
||||
if !path.starts_with("~") {
|
||||
Ok(path)
|
||||
} else if path == Path::new("~") {
|
||||
env::home_dir().map(Cow::Owned).ok_or_else(into_err)
|
||||
} else {
|
||||
let mut home_dir = env::home_dir().ok_or_else(into_err)?;
|
||||
if home_dir == Path::new("/") {
|
||||
let stripped = path.strip_prefix("~").map_err(|_e| into_err())?;
|
||||
Ok(Cow::Owned(stripped.into()))
|
||||
} else {
|
||||
home_dir.push(path.strip_prefix("~/").map_err(|_e| into_err())?);
|
||||
Ok(Cow::Owned(home_dir))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_path<'de, D: Deserializer<'de>>(de: D) -> Result<PathBuf, D::Error> {
|
||||
let path = PathBuf::deserialize(de)?;
|
||||
if let Ok(expanded_path) = expand_tilde(&path) {
|
||||
Ok(expanded_path.into())
|
||||
} else {
|
||||
Ok(path)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Config, Debug, Serialize, Deserialize)]
|
||||
pub struct EditorCfg {
|
||||
#[config(deserialize_with = deserialize_path, env = "EDITOR_PATH")]
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl Fallback for EditorCfg {
|
||||
fn fallback() -> <Self as Config>::Partial {
|
||||
Self::Partial {
|
||||
path: project_dir().map(|d| d.data_local_dir().join("editors/")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Config, Serialize, Deserialize)]
|
||||
pub struct ProjectCfg {
|
||||
#[config(deserialize_with = deserialize_path, env = "PROJECT_MANIFEST_PATH")]
|
||||
pub manifest_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Fallback for ProjectCfg {
|
||||
fn fallback() -> <Self as Config>::Partial {
|
||||
Self::Partial {
|
||||
manifest_path: project_dir().map(|d| d.data_local_dir().join("manifest.toml")),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Config, Serialize, Deserialize)]
|
||||
pub struct Cfg {
|
||||
#[config(nested)]
|
||||
pub editor: EditorCfg,
|
||||
|
||||
#[config(nested)]
|
||||
pub project: ProjectCfg,
|
||||
}
|
||||
|
||||
impl Cfg {
|
||||
pub fn from_env() -> Result<Cfg, Error> {
|
||||
let mut builder = Cfg::builder().env();
|
||||
|
||||
if let Some(dir) = project_dir() {
|
||||
builder = builder.file(dir.config_dir().join("config.toml"));
|
||||
}
|
||||
|
||||
builder
|
||||
.preloaded(Self::fallback())
|
||||
.load()
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl Fallback for Cfg {
|
||||
fn fallback() -> <Self as Config>::Partial {
|
||||
Self::Partial {
|
||||
editor: EditorCfg::fallback(),
|
||||
project: ProjectCfg::fallback(),
|
||||
}
|
||||
}
|
||||
}
|
1
core/src/editor.rs
Normal file
1
core/src/editor.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub struct Editor {}
|
795
core/src/editor_command.rs
Normal file
795
core/src/editor_command.rs
Normal file
|
@ -0,0 +1,795 @@
|
|||
use std::{
|
||||
ffi::OsString,
|
||||
net::IpAddr,
|
||||
ops::{Deref, DerefMut},
|
||||
path::PathBuf,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use derive_more::Display;
|
||||
use osstr_traits_derive::OsDisplay;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::collection::{CommandArgs, DelimitedVec};
|
||||
|
||||
type OsStrDisplay<'a> = std::ffi::os_str::Display<'a>;
|
||||
type PathDisplay<'a> = std::path::Display<'a>;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum ConsistencyCheckSourceMode {
|
||||
#[display("local")]
|
||||
Local,
|
||||
#[display("cacheserver")]
|
||||
CacheServer,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("{0} {1}", DelimitedVec::<PathDisplay>::from(exports), path.display())]
|
||||
#[os_display("{exports} {path}", exports = DelimitedVec::<&PathBuf, ' '>::from_iter(exports), path = path)]
|
||||
pub struct ExportPackage {
|
||||
path: PathBuf,
|
||||
exports: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum PlatformTextureFormat {
|
||||
#[display("dxt")]
|
||||
Dxt,
|
||||
#[display("pvrtc")]
|
||||
#[deprecated(note = "PVRTC format is deprecated. Use ASTC or ETC format instead.")]
|
||||
Pvrtc,
|
||||
#[display("atc")]
|
||||
Atc,
|
||||
#[display("etc")]
|
||||
Etc,
|
||||
#[display("etc2")]
|
||||
Etc2,
|
||||
#[display("astc")]
|
||||
Astc,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum TextureCompression {
|
||||
#[default]
|
||||
NoOverride,
|
||||
ForceUncompressed,
|
||||
ForceFastCompressor,
|
||||
ForceNoCrunchCompression,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum SharedLogLevel {
|
||||
#[display("debug")]
|
||||
Debug,
|
||||
#[display("info")]
|
||||
Info,
|
||||
#[display("notice")]
|
||||
Notice,
|
||||
#[display("fatal")]
|
||||
Fatal,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
pub enum PerforceArgument {
|
||||
#[display("vcPerforceHost {0}", _0.display())]
|
||||
#[os_display("vcPerforceHost {_0}")]
|
||||
Host(OsString),
|
||||
#[display("vcSharedLogLevel {_0}")]
|
||||
#[os_display("vcSharedLogLevel {_0}")]
|
||||
SharedLogLevel(SharedLogLevel),
|
||||
#[display("vcPerforceServer {0}", _0.display())]
|
||||
#[os_display("vcPerforceServer {_0}")]
|
||||
Server(OsString),
|
||||
#[display("vcPerforceWorkspace {0}", _0.display())]
|
||||
#[os_display("vcPerforceWorkspace {_0}")]
|
||||
Workspace(OsString),
|
||||
#[display("vcPerforceUsername {0}", _0.display())]
|
||||
#[os_display("vcPerforceUsername {_0}")]
|
||||
Username(OsString),
|
||||
#[display("vcPerforcePassword {0}", _0.display())]
|
||||
#[os_display("vcPerforcePassword {_0}")]
|
||||
Password(OsString),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum VcsMode {
|
||||
#[display("\"Visible Meta Files\"")]
|
||||
VisibleMetaFiles,
|
||||
#[display("\"Hidden Meta Files\"")]
|
||||
HiddenMetaFiles,
|
||||
#[display("Perforce {_0}")]
|
||||
#[os_display("Perforce {_0}")]
|
||||
Perforce(CommandArgs<PerforceArgument>),
|
||||
#[display("PlasticSCM")]
|
||||
PlasticScm,
|
||||
#[display("{0}", _0.display())]
|
||||
#[os_display("{_0}")]
|
||||
Other(OsString),
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum ConfigurationArgument {
|
||||
#[display("createProject \"{0}\"", _0.display())]
|
||||
#[os_display("-createProject \"{_0}\"")]
|
||||
CreateProject(PathBuf),
|
||||
#[display("consistencyCheck")]
|
||||
ConsistencyCheck,
|
||||
#[display("consistencyCheckSourceMode {_0}")]
|
||||
ConsistencyCheckSourceMode(ConsistencyCheckSourceMode),
|
||||
#[display("disable-assembly-updater {0}", DelimitedVec::<PathDisplay, ' '>::from(_0))]
|
||||
#[os_display("-disable-assembly-updater {}", DelimitedVec::<&PathBuf, ' '>::from_iter(_0))]
|
||||
DisableAssemblyUpdater(Vec<PathBuf>),
|
||||
#[display("disable-gpu-skinning")]
|
||||
DisableGpuSkinning,
|
||||
#[display("disable-playback-engines {0}", DelimitedVec::<OsStrDisplay, ' '>::from(_0))]
|
||||
#[os_display("-disable-playback-engines {}", DelimitedVec::<&std::ffi::OsString, ' '>::from_iter(_0))]
|
||||
DisablePlaybackEngines(Vec<OsString>),
|
||||
#[display("executeMethod {0}", _0.display())]
|
||||
#[os_display("-executeMethod {_0}")]
|
||||
ExecMethod(OsString),
|
||||
#[display("exportPackage {_0}")]
|
||||
#[os_display("-exportPackage {_0}")]
|
||||
ExportPackage(ExportPackage),
|
||||
#[display("importPackage {0}", _0.display())]
|
||||
#[os_display("-importPackage {_0}")]
|
||||
ImportPackage(PathBuf),
|
||||
#[display("job-worker-count {_0}")]
|
||||
JobWorkerCount(usize),
|
||||
#[display("gc-helper-count {_0}")]
|
||||
GcHelperCount(usize),
|
||||
#[display("logFile {0}", _0.display())]
|
||||
#[os_display("-logFile {_0}")]
|
||||
LogFile(PathBuf),
|
||||
#[display("noUpm")]
|
||||
NoUpm,
|
||||
#[display("openfile {0}", _0.display())]
|
||||
#[os_display("-openfile {_0}")]
|
||||
OpenFile(PathBuf),
|
||||
#[display("password {0}", _0.display())]
|
||||
#[os_display("-password {_0}")]
|
||||
Password(OsString),
|
||||
#[display("projectPath {0}", _0.display())]
|
||||
#[os_display("-projectPath {_0}")]
|
||||
ProjectPath(PathBuf),
|
||||
#[display("quit")]
|
||||
Quit,
|
||||
#[display("releaseCodeOptimization")]
|
||||
ReleaseCodeOptimization,
|
||||
#[display("setDefaultPlatformTextureFormat {_0}")]
|
||||
SetDefaultPlatformTextureFormat(PlatformTextureFormat),
|
||||
#[display("overrideMaxTextureSize {_0}")]
|
||||
OverrideMaxTextureSize(usize),
|
||||
#[display("overrideTextureCompression {_0}")]
|
||||
OverrideTextureCompression(TextureCompression),
|
||||
#[display("silent-crashes")]
|
||||
SilentCrashes,
|
||||
#[display("upmLogFile {0}", _0.display())]
|
||||
#[os_display("-upmLogFile {_0}")]
|
||||
UpmLogFile(PathBuf),
|
||||
#[display("username {0}", _0.display())]
|
||||
#[os_display("-username {_0}")]
|
||||
Username(OsString),
|
||||
#[display("vcsMode {_0}")]
|
||||
VcsMode(VcsMode),
|
||||
#[display("version")]
|
||||
Version,
|
||||
#[display("timestamps")]
|
||||
Timestamps,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum BatchModeArgument {
|
||||
#[display("accent-apiupdate")]
|
||||
AcceptApiUpdate,
|
||||
#[display("batchmode")]
|
||||
BatchMode,
|
||||
#[display("ignorecompilererrors")]
|
||||
IgnoreCompilerErrors,
|
||||
#[display("nographics")]
|
||||
NoGraphics,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum BuildTarget {
|
||||
#[display("win64")]
|
||||
Win64,
|
||||
#[display("win")]
|
||||
Win,
|
||||
#[display("osxuniversal")]
|
||||
OsxUniversal,
|
||||
#[display("linux64")]
|
||||
Linux64,
|
||||
#[display("android")]
|
||||
Android,
|
||||
#[display("ios")]
|
||||
IOs,
|
||||
#[display("webgl")]
|
||||
WebGl,
|
||||
#[display("tvos")]
|
||||
TvOs,
|
||||
#[display("windowsstoreapps")]
|
||||
WindowsStoreApps,
|
||||
#[display("cloudrendering")]
|
||||
CloudRendering,
|
||||
#[display("visionos")]
|
||||
VisionOs,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum BuildSubtarget {
|
||||
Player,
|
||||
Server,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
pub enum BuildArgument {
|
||||
#[display("activeBuildProfile \"{0}\"", _0.display())]
|
||||
#[os_display("activeBuildProfile \"{_0}\"")]
|
||||
ActiveBuildProfile(PathBuf),
|
||||
#[display("build \"{0}\"", _0.display())]
|
||||
#[os_display("build \"{_0}\"")]
|
||||
Build(PathBuf),
|
||||
#[display("buildLinux64Player \"{0}\"", _0.display())]
|
||||
#[os_display("buildLinux64Player \"{_0}\"")]
|
||||
BuildLinux64Player(PathBuf),
|
||||
#[display("buildLinuxHeadlessSimulation \"{0}\"", _0.display())]
|
||||
#[os_display("buildLinuxHeadlessSimulation \"{_0}\"")]
|
||||
BuildLinuxHeadlessSimulation(PathBuf),
|
||||
#[display("buildOSXUniversalPlayer \"{0}\"", _0.display())]
|
||||
#[os_display("buildOSXUniversalPlayer \"{_0}\"")]
|
||||
BuildOsxUniversalPlayer(PathBuf),
|
||||
#[display("buildTarget \"{_0}\"")]
|
||||
BuildTarget(BuildTarget),
|
||||
#[display("standaloneBuildSubtarget \"{_0}\"")]
|
||||
#[os_display("standaloneBuildSubtarget \"{_0}\"")]
|
||||
StandaloneBuildSubtarget(BuildSubtarget),
|
||||
#[display("buildWindowsPlayer \"{0}\"", _0.display())]
|
||||
#[os_display("buildWindowsPlayer \"{_0}\"")]
|
||||
BuildWindowsPlayer(PathBuf),
|
||||
#[display("buildWindows64Player \"{0}\"", _0.display())]
|
||||
#[os_display("buildWindows64Player \"{_0}\"")]
|
||||
BuildWindows64Player(PathBuf),
|
||||
}
|
||||
#[derive(Debug, Display, Clone, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum CacheServerArgument {
|
||||
#[display("EnableCacheServer")]
|
||||
Enable,
|
||||
#[display("cacheServerEndpoint {_0}:{_1}")]
|
||||
Endpoint(IpAddr, u16),
|
||||
#[display("cacheServerNamespacePrefix \"{0}\"", _0.display())]
|
||||
#[os_display("cacheServerNamespacePrefix \"{_0}\"")]
|
||||
NamespacePrefix(OsString),
|
||||
#[display("cacheServerEnableDownload {_0}")]
|
||||
EnableDownload(bool),
|
||||
#[display("cacheServerEnableUpload {_0}")]
|
||||
EnableUpload(bool),
|
||||
#[display("cacheServerWaitForConnection {0}", _0.as_millis())]
|
||||
WaitForConnection(Duration),
|
||||
#[display("cacheServerWaitForUploadCompletion")]
|
||||
WaitForUploadCompletion,
|
||||
#[display("cacheServerDownloadBatchSize {_0}")]
|
||||
DownloadBatchSize(usize),
|
||||
#[display("cacheServerUploadAllRevisions")]
|
||||
UploadAllRevisions,
|
||||
#[display("cacheServerUploadExistingShaderCache")]
|
||||
UploadExistingShaderCache,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[os_display(from_display)]
|
||||
pub enum StackTraceLogType {
|
||||
None,
|
||||
#[display("\"Script Only\"")]
|
||||
ScriptOnly,
|
||||
#[default]
|
||||
Full,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum DebugArgument {
|
||||
#[display("disableManagedDebugger")]
|
||||
DisableManagedDebugger,
|
||||
#[display("diag-debug-shader-compiler")]
|
||||
DiagDebugShaderCompiler,
|
||||
#[display("debugCodeOptimization")]
|
||||
DebugCodeOptimization,
|
||||
#[display("enableCodeCoverage")]
|
||||
EnableCodeCoverage,
|
||||
#[display("force-d3d12-debug")]
|
||||
ForceD3d12Debug,
|
||||
#[display("force-d3d12-debug-gbv")]
|
||||
ForceD3d12DebugGbv,
|
||||
#[display("force-vulkan-layers")]
|
||||
ForceVulkanLayers,
|
||||
#[display("StackTraceLogType {_0}")]
|
||||
#[os_display("StackTraceLogType {_0}")]
|
||||
StackTraceLogType(StackTraceLogType),
|
||||
#[display("log-memory-performance-stats")]
|
||||
LogMemoryPerformanceStats,
|
||||
#[display("wait-for-managed-debugger")]
|
||||
WaitForManagedDebugger,
|
||||
#[display("wait-for-native-debugger")]
|
||||
WaitForNativeDebugger,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum GraphicsApiArgument {
|
||||
#[display("force-clamped")]
|
||||
ForceClamped,
|
||||
#[display("force-d3d11")]
|
||||
ForceD3d11,
|
||||
#[display("force-d3d12")]
|
||||
ForceD3d12,
|
||||
#[display("force-device-index")]
|
||||
ForceDeviceIndex,
|
||||
#[display("force-glcore")]
|
||||
ForceGlCore,
|
||||
#[display("force-glcoreXY")]
|
||||
ForceGlCoreXy,
|
||||
#[display("force-gles")]
|
||||
ForceGlEs,
|
||||
#[display("force-glesXY")]
|
||||
ForceGlEsXy,
|
||||
#[display("force-opengl")]
|
||||
ForceOpenGl,
|
||||
#[display("force-vulkan")]
|
||||
ForceVulkan,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum LicenseArgument {
|
||||
#[display("createManualActivationFile")]
|
||||
CreateManualActivationFile,
|
||||
#[display("manualLicenseFile {0}", _0.display())]
|
||||
#[os_display("manualLicenseFile {_0}")]
|
||||
ManualLicenseFile(PathBuf),
|
||||
#[display("returnlicense")]
|
||||
ReturnLicense,
|
||||
#[display("serial {0}", _0.display())]
|
||||
#[os_display("serial {_0}")]
|
||||
Serial(OsString),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum MetalArgument {
|
||||
#[display("force-low-power-device")]
|
||||
ForceLowPowerDevice,
|
||||
#[display("force-metal")]
|
||||
ForceMetal,
|
||||
#[display("enable-metal-capture")]
|
||||
EnableMetalCapture,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum ProfilerArgument {
|
||||
#[display("deepprofiling")]
|
||||
DeepProfiling,
|
||||
#[display("profiler-enable")]
|
||||
Enable,
|
||||
#[display("profiler-log-file {0}", _0.display())]
|
||||
#[os_display("profiler-log-file {_0}")]
|
||||
LogFile(PathBuf),
|
||||
#[display("profiler-capture-frame-count {_0}")]
|
||||
CaptureFrameCount(usize),
|
||||
#[display("profiler-maxusedmemory {_0}")]
|
||||
MaxUsedMemory(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, OsDisplay)]
|
||||
#[display("-{_variant}")]
|
||||
#[os_display(from_display)]
|
||||
pub enum EditorSpecialArgument {
|
||||
#[display("enableIncompatibleAssetDowngrade")]
|
||||
EnableIncompatibleAssetDowngrade,
|
||||
#[display("giCustomCacheLocation {0}", _0.display())]
|
||||
#[os_display("giCustomCacheLocation {_0}")]
|
||||
GiCustomCacheLocation(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum UnityArgument {
|
||||
Configuration(ConfigurationArgument),
|
||||
BatchMode(BatchModeArgument),
|
||||
Build(BuildArgument),
|
||||
CacheServer(CacheServerArgument),
|
||||
Debug(DebugArgument),
|
||||
GraphicsApi(GraphicsApiArgument),
|
||||
License(LicenseArgument),
|
||||
Metal(MetalArgument),
|
||||
Profiler(ProfilerArgument),
|
||||
Editor(EditorSpecialArgument),
|
||||
Extra(OsString),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct UnityArguments(Vec<UnityArgument>);
|
||||
|
||||
impl Deref for UnityArguments {
|
||||
type Target = Vec<UnityArgument>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for UnityArguments {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for UnityArguments {
|
||||
fn default() -> Self {
|
||||
Self(Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! unity_args {
|
||||
() => {
|
||||
UnityArguments::default()
|
||||
};
|
||||
|
||||
($arg:expr $(, $rest:expr)* $(,)?) => {
|
||||
{
|
||||
let mut args = Vec::new();
|
||||
$(
|
||||
#[allow(unreachable_patterns)]
|
||||
match $rest {
|
||||
arg @ ConfigArguments::CreateProject(_) |
|
||||
arg @ ConfigArguments::ConsistencyCheck |
|
||||
arg @ ConfigArguments::ConsistencyCheckSourceMode(_) |
|
||||
arg @ ConfigArguments::DisableAssemblyUpdater(_) |
|
||||
arg @ ConfigArguments::DisableGpuSkinning |
|
||||
arg @ ConfigArguments::DisablePlaybackEngines(_) |
|
||||
arg @ ConfigArguments::ExecMethod(_) |
|
||||
arg @ ConfigArguments::ExportPackage(_) |
|
||||
arg @ ConfigArguments::ImportPackage(_) |
|
||||
arg @ ConfigArguments::JobWorkerCount(_) |
|
||||
arg @ ConfigArguments::GcHelperCount(_) |
|
||||
arg @ ConfigArguments::LogFile(_) |
|
||||
arg @ ConfigArguments::NoUpm |
|
||||
arg @ ConfigArguments::OpenFile(_) |
|
||||
arg @ ConfigArguments::Password(_) |
|
||||
arg @ ConfigArguments::ProjectPath(_) |
|
||||
arg @ ConfigArguments::Quit |
|
||||
arg @ ConfigArguments::ReleaseCodeOptimization |
|
||||
arg @ ConfigArguments::SetDefaultPlatformTextureFormat |
|
||||
arg @ ConfigArguments::OverrideMaxTextureSize(_) |
|
||||
arg @ ConfigArguments::OverrideTextureCompression(_) |
|
||||
arg @ ConfigArguments::SilentCrashes |
|
||||
arg @ ConfigArguments::UpmLogFile(_) |
|
||||
arg @ ConfigArguments::Username(_) |
|
||||
arg @ ConfigArguments::VcsMode |
|
||||
arg @ ConfigArguments::Version |
|
||||
arg @ ConfigArguments::Timestamps => {
|
||||
args.push(UnityArgument::Configuration(arg));
|
||||
},
|
||||
|
||||
arg @ BatchModeArguments::AcceptApiUpdate |
|
||||
arg @ BatchModeArguments::BatchMode |
|
||||
arg @ BatchModeArguments::IgnoreCompileErrors |
|
||||
arg @ BatchModeArguments::NoGraphics => {
|
||||
args.push(UnityArgument::BatchMode(arg));
|
||||
},
|
||||
|
||||
arg @ BuildArguments::ActiveBuildProfile(_) |
|
||||
arg @ BuildArguments::Build(_) |
|
||||
arg @ BuildArguments::BuildLinux64Player(_) |
|
||||
arg @ BuildArguments::BuildLinuxHeadlessSimulation(_) |
|
||||
arg @ BuildArguments::BuildOSXUniversalPlayer(_) |
|
||||
arg @ BuildArguments::BuildTarget(_) |
|
||||
arg @ BuildArguments::StandaloneBuildSubtarget(_) |
|
||||
arg @ BuildArguments::BuildWindowsPlayer(_) |
|
||||
arg @ BuildArguments::BuildWindows64Player(_) => {
|
||||
args.push(UnityArgument::Build(arg));
|
||||
},
|
||||
|
||||
arg @ CacheServerArguments::Enable |
|
||||
arg @ CacheServerArguments::Endpoint(_, _) |
|
||||
arg @ CacheServerArguments::NamespacePrefix(_) |
|
||||
arg @ CacheServerArguments::EnableDownload(_) |
|
||||
arg @ CacheServerArguments::EnableUpload(_) |
|
||||
arg @ CacheServerArguments::WaitForConnection(_) |
|
||||
arg @ CacheServerArguments::WaitForUploadCompletion |
|
||||
arg @ CacheServerArguments::DownloadBatchSize(_) |
|
||||
arg @ CacheServerArguments::UploadAllRevisions |
|
||||
arg @ CacheServerArguments::UploadExistingShaderCache => {
|
||||
args.push(UnityArgument::CacheServer(arg));
|
||||
},
|
||||
|
||||
arg @ DebugArguments::DisableManagedDebugger |
|
||||
arg @ DebugArguments::DiagDebugShaderCompiler |
|
||||
arg @ DebugArguments::DebugCodeOptimization |
|
||||
arg @ DebugArguments::EnableCodeCoverage |
|
||||
arg @ DebugArguments::ForceD3d12Debug |
|
||||
arg @ DebugArguments::ForceD3d12DebugGbv |
|
||||
arg @ DebugArguments::ForceVulkanLayers |
|
||||
arg @ DebugArguments::StackTraceLogType(_) |
|
||||
arg @ DebugArguments::LogMemoryPerformanceStats |
|
||||
arg @ DebugArguments::WaitForManagedDebugger |
|
||||
arg @ DebugArguments::WaitForNativeDebugger => {
|
||||
args.push(UnityArgument::Debug(arg));
|
||||
},
|
||||
|
||||
arg @ GraphicsApiArguments::ForceClamped |
|
||||
arg @ GraphicsApiArguments::ForceD3d11 |
|
||||
arg @ GraphicsApiArguments::ForceD3d12 |
|
||||
arg @ GraphicsApiArguments::ForceDeviceIndex |
|
||||
arg @ GraphicsApiArguments::ForceGlCore |
|
||||
arg @ GraphicsApiArguments::ForceGlCoreXy |
|
||||
arg @ GraphicsApiArguments::ForceGlEs |
|
||||
arg @ GraphicsApiArguments::ForceGlEsXy |
|
||||
arg @ GraphicsApiArguments::ForceOpenGl |
|
||||
arg @ GraphicsApiArguments::ForceVulkan => {
|
||||
args.push(UnityArgument::GraphicsApi(arg));
|
||||
},
|
||||
|
||||
arg @ LicenseArguments::CreateManualActivationFile |
|
||||
arg @ LicenseArguments::ManualLicenseFile(_) |
|
||||
arg @ LicenseArguments::ReturnLicense |
|
||||
arg @ LicenseArguments::Serial(_) => {
|
||||
args.push(UnityArgument::License(arg));
|
||||
},
|
||||
|
||||
arg @ MetalArguments::ForceLowPowerDevice |
|
||||
arg @ MetalArguments::ForceMetal |
|
||||
arg @ MetalArguments::EnableMetalCapture => {
|
||||
args.push(UnityArgument::Metal(arg));
|
||||
},
|
||||
|
||||
arg @ ProfilerArguments::DeepProfiling |
|
||||
arg @ ProfilerArguments::Enable |
|
||||
arg @ ProfilerArguments::LogFile(_) |
|
||||
arg @ ProfilerArguments::CaptureFrameCount(_) |
|
||||
arg @ ProfilerArguments::MaxUsedMemory(_) => {
|
||||
args.push(UnityArgument::Profiler(arg));
|
||||
},
|
||||
|
||||
arg @ EditorSpecialArguments::EnableIncompatibleAssetDowngrade |
|
||||
arg @ EditorSpecialArguments::GiCustomCacheLocation(_) => {
|
||||
args.push(UnityArgument::Editor(arg));
|
||||
},
|
||||
|
||||
arg @ UnityArgument::Configuration(_) |
|
||||
arg @ UnityArgument::BatchMode(_) |
|
||||
arg @ UnityArgument::Build(_) |
|
||||
arg @ UnityArgument::CacheServer(_) |
|
||||
arg @ UnityArgument::Debug(_) |
|
||||
arg @ UnityArgument::GraphicsApi(_) |
|
||||
arg @ UnityArgument::License(_) |
|
||||
arg @ UnityArgument::Metal(_) |
|
||||
arg @ UnityArgument::Profiler(_) |
|
||||
arg @ UnityArgument::Editor(_) |
|
||||
arg @ UnityArgument::Extra(_) => {
|
||||
args.push(arg);
|
||||
},
|
||||
|
||||
s: OsString => {
|
||||
args.push(UnityArgument::Extra(s));
|
||||
},
|
||||
|
||||
_ => compile_error!("Unsupported argument type in unity_args! macro. Ensure it's a valid argument enum variant or a String."),
|
||||
}
|
||||
)*
|
||||
|
||||
UnityArguments(args)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditorCommand {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{ffi::OsString, path::PathBuf};
|
||||
|
||||
use osstr_traits::ToOsString;
|
||||
|
||||
use crate::{
|
||||
collection::CommandArgs,
|
||||
editor_command::{
|
||||
ConfigurationArgument, ExportPackage, PerforceArgument, PlatformTextureFormat,
|
||||
SharedLogLevel, TextureCompression, VcsMode,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn config_args() {
|
||||
let arg = ConfigurationArgument::CreateProject(PathBuf::from("./test-project"));
|
||||
assert_eq!(arg.to_os_string(), "-createProject \"./test-project\"");
|
||||
|
||||
let arg = ConfigurationArgument::ConsistencyCheck;
|
||||
assert_eq!(arg.to_os_string(), "-consistencyCheck");
|
||||
|
||||
let arg = ConfigurationArgument::ConsistencyCheckSourceMode(
|
||||
super::ConsistencyCheckSourceMode::Local,
|
||||
);
|
||||
assert_eq!(arg.to_os_string(), "-consistencyCheckSourceMode local");
|
||||
|
||||
let arg = ConfigurationArgument::ConsistencyCheckSourceMode(
|
||||
super::ConsistencyCheckSourceMode::CacheServer,
|
||||
);
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-consistencyCheckSourceMode cacheserver"
|
||||
);
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::DisableAssemblyUpdater(vec!["a.dll".into(), "b.dll".into()]);
|
||||
assert_eq!(arg.to_os_string(), "-disable-assembly-updater a.dll b.dll");
|
||||
|
||||
let arg = ConfigurationArgument::DisableGpuSkinning;
|
||||
assert_eq!(arg.to_os_string(), "-disable-gpu-skinning");
|
||||
|
||||
let arg = ConfigurationArgument::DisablePlaybackEngines(vec![
|
||||
"AndroidPlayer".into(),
|
||||
"iOSSupport".into(),
|
||||
]);
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-disable-playback-engines AndroidPlayer iOSSupport"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::ExecMethod("NamespaceName.ClassName.MethodName".into());
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-executeMethod NamespaceName.ClassName.MethodName"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::ExportPackage(ExportPackage {
|
||||
path: "export.unitypackage".into(),
|
||||
exports: vec!["Assets/a.asset".into(), "Assets/b.asset".into()],
|
||||
});
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-exportPackage Assets/a.asset Assets/b.asset export.unitypackage"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::ImportPackage(PathBuf::from("./package.unitypackage"));
|
||||
assert_eq!(arg.to_os_string(), "-importPackage ./package.unitypackage");
|
||||
|
||||
let arg = ConfigurationArgument::JobWorkerCount(8usize);
|
||||
assert_eq!(arg.to_os_string(), "-job-worker-count 8");
|
||||
|
||||
let arg = ConfigurationArgument::GcHelperCount(12usize);
|
||||
assert_eq!(arg.to_os_string(), "-gc-helper-count 12");
|
||||
|
||||
let arg = ConfigurationArgument::LogFile(PathBuf::from("/var/log/unity/editor.log"));
|
||||
assert_eq!(arg.to_os_string(), "-logFile /var/log/unity/editor.log");
|
||||
|
||||
let arg = ConfigurationArgument::NoUpm;
|
||||
assert_eq!(arg.to_os_string(), "-noUpm");
|
||||
|
||||
let arg = ConfigurationArgument::OpenFile(PathBuf::from("./scene.unity"));
|
||||
assert_eq!(arg.to_os_string(), "-openfile ./scene.unity");
|
||||
|
||||
let arg = ConfigurationArgument::Password(OsString::from("hunter12"));
|
||||
assert_eq!(arg.to_os_string(), "-password hunter12");
|
||||
|
||||
let arg = ConfigurationArgument::ProjectPath(PathBuf::from("./my-project/"));
|
||||
assert_eq!(arg.to_os_string(), "-projectPath ./my-project/");
|
||||
|
||||
let arg = ConfigurationArgument::Quit;
|
||||
assert_eq!(arg.to_os_string(), "-quit");
|
||||
|
||||
let arg = ConfigurationArgument::ReleaseCodeOptimization;
|
||||
assert_eq!(arg.to_os_string(), "-releaseCodeOptimization");
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::SetDefaultPlatformTextureFormat(PlatformTextureFormat::Dxt);
|
||||
assert_eq!(arg.to_os_string(), "-setDefaultPlatformTextureFormat dxt");
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::SetDefaultPlatformTextureFormat(PlatformTextureFormat::Atc);
|
||||
assert_eq!(arg.to_os_string(), "-setDefaultPlatformTextureFormat atc");
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::SetDefaultPlatformTextureFormat(PlatformTextureFormat::Etc);
|
||||
assert_eq!(arg.to_os_string(), "-setDefaultPlatformTextureFormat etc");
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::SetDefaultPlatformTextureFormat(PlatformTextureFormat::Etc2);
|
||||
assert_eq!(arg.to_os_string(), "-setDefaultPlatformTextureFormat etc2");
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::SetDefaultPlatformTextureFormat(PlatformTextureFormat::Pvrtc);
|
||||
assert_eq!(arg.to_os_string(), "-setDefaultPlatformTextureFormat pvrtc");
|
||||
|
||||
let arg =
|
||||
ConfigurationArgument::SetDefaultPlatformTextureFormat(PlatformTextureFormat::Astc);
|
||||
assert_eq!(arg.to_os_string(), "-setDefaultPlatformTextureFormat astc");
|
||||
|
||||
let arg = ConfigurationArgument::OverrideMaxTextureSize(256usize);
|
||||
assert_eq!(arg.to_os_string(), "-overrideMaxTextureSize 256");
|
||||
|
||||
let arg = ConfigurationArgument::OverrideTextureCompression(TextureCompression::NoOverride);
|
||||
assert_eq!(arg.to_os_string(), "-overrideTextureCompression NoOverride");
|
||||
|
||||
let arg = ConfigurationArgument::OverrideTextureCompression(
|
||||
TextureCompression::ForceUncompressed,
|
||||
);
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-overrideTextureCompression ForceUncompressed"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::OverrideTextureCompression(
|
||||
TextureCompression::ForceFastCompressor,
|
||||
);
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-overrideTextureCompression ForceFastCompressor"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::OverrideTextureCompression(
|
||||
TextureCompression::ForceNoCrunchCompression,
|
||||
);
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-overrideTextureCompression ForceNoCrunchCompression"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::SilentCrashes;
|
||||
assert_eq!(arg.to_os_string(), "-silent-crashes");
|
||||
|
||||
let arg = ConfigurationArgument::UpmLogFile(PathBuf::from("/var/log/unity/upm.log"));
|
||||
assert_eq!(arg.to_os_string(), "-upmLogFile /var/log/unity/upm.log");
|
||||
|
||||
let arg = ConfigurationArgument::Username(OsString::from("kitsucafe"));
|
||||
assert_eq!(arg.to_os_string(), "-username kitsucafe");
|
||||
|
||||
let arg = ConfigurationArgument::VcsMode(VcsMode::VisibleMetaFiles);
|
||||
assert_eq!(arg.to_os_string(), "-vcsMode \"Visible Meta Files\"");
|
||||
|
||||
let arg = ConfigurationArgument::VcsMode(VcsMode::HiddenMetaFiles);
|
||||
assert_eq!(arg.to_os_string(), "-vcsMode \"Hidden Meta Files\"");
|
||||
|
||||
let arg = ConfigurationArgument::VcsMode(VcsMode::PlasticScm);
|
||||
assert_eq!(arg.to_os_string(), "-vcsMode PlasticSCM");
|
||||
|
||||
let arg = ConfigurationArgument::VcsMode(VcsMode::Perforce(CommandArgs(vec![
|
||||
PerforceArgument::Workspace("TestWorkspace".into()),
|
||||
PerforceArgument::Host("Hostname".into()),
|
||||
PerforceArgument::Server("8.8.8.8".into()),
|
||||
PerforceArgument::SharedLogLevel(SharedLogLevel::Info),
|
||||
PerforceArgument::Username("kitsucafe".into()),
|
||||
PerforceArgument::Password("hunter12".into()),
|
||||
])));
|
||||
assert_eq!(
|
||||
arg.to_os_string(),
|
||||
"-vcsMode Perforce -vcPerforceWorkspace TestWorkspace -vcPerforceHost Hostname -vcPerforceServer 8.8.8.8 -vcSharedLogLevel info -vcPerforceUsername kitsucafe -vcPerforcePassword hunter12"
|
||||
);
|
||||
|
||||
let arg = ConfigurationArgument::Version;
|
||||
assert_eq!(arg.to_os_string(), "-version");
|
||||
|
||||
let arg = ConfigurationArgument::Timestamps;
|
||||
assert_eq!(arg.to_os_string(), "-timestamps");
|
||||
}
|
||||
}
|
113
core/src/error.rs
Normal file
113
core/src/error.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
use std::{error::Error as StdError, fmt::Display, path::PathBuf};
|
||||
use toml::de::Error as TomlError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShellExpansionError {
|
||||
variable: String,
|
||||
context: Option<String>,
|
||||
}
|
||||
|
||||
impl ShellExpansionError {
|
||||
pub fn new(variable: &str, context: Option<&str>) -> Self {
|
||||
Self {
|
||||
variable: variable.into(),
|
||||
context: context.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ShellExpansionError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(context) = &self.context {
|
||||
write!(f, "Error expanding {} in {}", self.variable, context)
|
||||
} else {
|
||||
write!(f, "Error expanding {}", self.variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileError {
|
||||
path: PathBuf,
|
||||
source: Box<dyn StdError>,
|
||||
}
|
||||
|
||||
impl FileError {
|
||||
pub fn new(path: impl Into<PathBuf>, source: impl Into<Box<dyn StdError>>) -> Self {
|
||||
Self {
|
||||
path: path.into(),
|
||||
source: source.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FileError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Error handling \"{}\": {}",
|
||||
self.path.display(),
|
||||
&self.source
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for FileError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ProjectManifestError {
|
||||
Read(FileError),
|
||||
Parse(TomlError),
|
||||
}
|
||||
|
||||
impl From<FileError> for ProjectManifestError {
|
||||
fn from(value: FileError) -> Self {
|
||||
Self::Read(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TomlError> for ProjectManifestError {
|
||||
fn from(value: TomlError) -> Self {
|
||||
Self::Parse(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ProjectManifestError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Read(error) => write!(f, "Error reading project manifest: {error}"),
|
||||
Self::Parse(error) => write!(f, "Error parsing project manifest: {error}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ProjectManifestError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
LoadConfig(confique::Error),
|
||||
ProjectManifest(ProjectManifestError),
|
||||
}
|
||||
|
||||
impl From<confique::Error> for Error {
|
||||
fn from(value: confique::Error) -> Self {
|
||||
Self::LoadConfig(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProjectManifestError> for Error {
|
||||
fn from(value: ProjectManifestError) -> Self {
|
||||
Self::ProjectManifest(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::LoadConfig(error) => write!(f, "Couldn't load config: {error}"),
|
||||
Error::ProjectManifest(error) => write!(f, "Couldn't read projects: {error}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
101
core/src/lib.rs
Normal file
101
core/src/lib.rs
Normal file
|
@ -0,0 +1,101 @@
|
|||
#![feature(min_specialization)]
|
||||
|
||||
pub mod collection;
|
||||
pub mod config;
|
||||
pub mod editor;
|
||||
pub mod editor_command;
|
||||
pub mod error;
|
||||
pub mod project;
|
||||
|
||||
use std::{fs, ops::Deref, path::Path};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
config::Cfg,
|
||||
editor::Editor,
|
||||
error::{Error, FileError, ProjectManifestError},
|
||||
project::Project,
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Projects {
|
||||
projects: Vec<Project>,
|
||||
}
|
||||
|
||||
impl Projects {
|
||||
pub fn new(projects: Vec<Project>) -> Self {
|
||||
Self { projects }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Project>> for Projects {
|
||||
fn from(value: Vec<Project>) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Projects {
|
||||
fn default() -> Self {
|
||||
Self::new(Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Projects {
|
||||
type Target = Vec<Project>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.projects
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TormentNexus {
|
||||
config: Cfg,
|
||||
projects: Projects,
|
||||
}
|
||||
|
||||
impl TormentNexus {
|
||||
pub fn new(config: Cfg, projects: impl Into<Projects>) -> Self {
|
||||
Self {
|
||||
config,
|
||||
projects: projects.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load() -> Result<Self, Error> {
|
||||
let config = Cfg::from_env()?;
|
||||
let projects = Self::read_projects(&config.project.manifest_path)?;
|
||||
|
||||
Ok(Self::new(config, projects))
|
||||
}
|
||||
|
||||
pub fn read_projects(
|
||||
manifest_path: impl AsRef<Path>,
|
||||
) -> Result<Projects, ProjectManifestError> {
|
||||
let content = fs::read_to_string(&manifest_path)
|
||||
.map_err(|err| FileError::new(manifest_path.as_ref(), err))?;
|
||||
|
||||
Ok(toml::from_str::<Projects>(&content)?)
|
||||
}
|
||||
|
||||
pub fn installed_editors(&self) -> Vec<Editor> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
pub fn projects(&self) -> &Projects {
|
||||
&self.projects
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::TormentNexus;
|
||||
|
||||
#[test]
|
||||
fn without_cfg() {
|
||||
let hub = TormentNexus::load();
|
||||
println!("{hub:?}");
|
||||
assert!(hub.is_ok())
|
||||
}
|
||||
}
|
10
core/src/project.rs
Normal file
10
core/src/project.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Project {
|
||||
pub name: String,
|
||||
pub editor: String,
|
||||
pub path: PathBuf,
|
||||
}
|
6
gui/Cargo.toml
Normal file
6
gui/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "gui"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
3
gui/src/main.rs
Normal file
3
gui/src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
2
rust-toolchain.toml
Normal file
2
rust-toolchain.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly"
|
Loading…
Add table
Reference in a new issue