ability to select engine version for a project in the project manager

This commit is contained in:
Dmitry Stepanov
2024-12-10 22:15:17 +03:00
parent ef1d594bd4
commit e78b7d35c8
3 changed files with 199 additions and 84 deletions
+123 -21
View File
@@ -23,51 +23,120 @@ use fyrox::{
core::{log::Log, pool::Handle},
gui::{
button::ButtonMessage,
dropdown_list::DropdownListBuilder,
dropdown_list::{DropdownListBuilder, DropdownListMessage},
grid::{Column, GridBuilder, Row},
message::{MessageDirection, UiMessage},
stack_panel::StackPanelBuilder,
text::TextBuilder,
text::{TextBuilder, TextMessage},
text_box::TextBoxBuilder,
utils::make_dropdown_list_option,
widget::WidgetBuilder,
widget::WidgetMessage,
window::{WindowBuilder, WindowMessage, WindowTitle},
BuildContext, HorizontalAlignment, Orientation, Thickness, UiNode, UserInterface,
VerticalAlignment,
},
};
#[allow(dead_code)]
enum Version {
Specific(String),
Local,
Nightly,
}
impl Version {
fn index(&self) -> usize {
match self {
Version::Specific(_) => 0,
Version::Local => 1,
Version::Nightly => 2,
}
}
fn as_string_version(&self) -> String {
match self {
Version::Specific(ver) => ver.clone(),
Version::Local => "latest".to_string(),
Version::Nightly => "nightly".to_string(),
}
}
}
pub struct UpgradeTool {
window: Handle<UiNode>,
version: Handle<UiNode>,
version_selector: Handle<UiNode>,
version_type_selector: Handle<UiNode>,
upgrade: Handle<UiNode>,
cancel: Handle<UiNode>,
selected_version: Version,
version_input_field: Handle<UiNode>,
}
impl UpgradeTool {
pub fn new(project: &Project, ctx: &mut BuildContext) -> Self {
let version = utils::fyrox_version_or_default(&project.manifest_path);
let dependency = utils::fyrox_dependency_from_path(&project.manifest_path).unwrap();
let version = TextBuilder::new(
WidgetBuilder::new()
.on_row(0)
.with_margin(Thickness::uniform(1.0)),
)
.with_text(format!("Current Engine Version: {version}"))
.with_text(format!(
"Current Engine Version: {}\nSource: {}",
dependency.req,
dependency
.source
.as_ref()
.map(|s| s.to_string())
.or_else(|| dependency.path.as_ref().map(|s| s.to_string()))
.unwrap_or_default()
))
.build(ctx);
let version_selector = DropdownListBuilder::new(
let is_local = dependency.path.is_some();
let is_git = dependency.source.as_ref().map_or(false, |s| {
s.contains("https://github.com/FyroxEngine/Fyrox")
});
let selected_version = if is_local {
Version::Local
} else if is_git {
Version::Nightly
} else {
Version::Specific(dependency.name.clone())
};
let version_type_selector = DropdownListBuilder::new(
WidgetBuilder::new()
.with_tab_index(Some(0))
.on_row(1)
.with_margin(Thickness::uniform(1.0)),
)
.with_close_on_selection(true)
.with_items(vec![
make_dropdown_list_option(ctx, "Specific"),
make_dropdown_list_option(ctx, "Latest"),
make_dropdown_list_option(ctx, "Local"),
make_dropdown_list_option(ctx, "Nightly"),
])
.with_selected(0)
.with_selected(selected_version.index())
.build(ctx);
let version_input_field = TextBoxBuilder::new(
WidgetBuilder::new()
.with_visibility(!is_local)
.with_height(22.0)
.with_margin(Thickness::uniform(1.0)),
)
.with_vertical_text_alignment(VerticalAlignment::Center)
.with_text(dependency.req.to_string())
.build(ctx);
let controls = StackPanelBuilder::new(
WidgetBuilder::new()
.with_child(version)
.with_child(version_type_selector)
.with_child(version_input_field),
)
.build(ctx);
let upgrade;
@@ -75,7 +144,7 @@ impl UpgradeTool {
let buttons = StackPanelBuilder::new(
WidgetBuilder::new()
.with_horizontal_alignment(HorizontalAlignment::Right)
.on_row(3)
.on_row(2)
.with_child({
upgrade = make_button("Upgrade", 130.0, 25.0, 1, 0, 0, None, ctx);
upgrade
@@ -90,18 +159,16 @@ impl UpgradeTool {
let content = GridBuilder::new(
WidgetBuilder::new()
.with_child(version)
.with_child(version_selector)
.with_child(controls)
.with_child(buttons),
)
.add_column(Column::stretch())
.add_row(Row::auto())
.add_row(Row::auto())
.add_row(Row::stretch())
.add_row(Row::auto())
.build(ctx);
let window = WindowBuilder::new(WidgetBuilder::new().with_width(300.0).with_height(200.0))
let window = WindowBuilder::new(WidgetBuilder::new().with_width(400.0).with_height(130.0))
.open(false)
.with_title(WindowTitle::text("Upgrade Project"))
.with_content(content)
@@ -120,25 +187,29 @@ impl UpgradeTool {
Self {
window,
version,
version_selector,
version_type_selector,
upgrade,
cancel,
selected_version,
version_input_field,
}
}
pub fn handle_ui_message(
self,
mut self,
message: &UiMessage,
ui: &mut UserInterface,
project: &Project,
) -> Option<Self> {
if let Some(ButtonMessage::Click) = message.data() {
if message.destination() == self.upgrade {
Log::verify(fyrox_template_core::upgrade_project(
&project.manifest_path,
"",
false,
));
if let Some(parent) = project.manifest_path.parent() {
Log::verify(fyrox_template_core::upgrade_project(
parent,
&self.selected_version.as_string_version(),
matches!(self.selected_version, Version::Local),
));
}
} else if message.destination() == self.cancel {
ui.send_message(WindowMessage::close(
self.window,
@@ -149,6 +220,37 @@ impl UpgradeTool {
if message.destination() == self.window {
return None;
}
} else if let Some(DropdownListMessage::SelectionChanged(Some(index))) = message.data() {
if message.destination() == self.version_type_selector {
match *index {
0 => {
self.selected_version = Version::Specific(
fyrox_template_core::CURRENT_ENGINE_VERSION.to_string(),
);
}
1 => {
self.selected_version = Version::Local;
}
2 => {
self.selected_version = Version::Nightly;
}
_ => (),
}
ui.send_message(WidgetMessage::visibility(
self.version_input_field,
MessageDirection::ToWidget,
matches!(self.selected_version, Version::Specific(_)),
))
}
} else if let Some(TextMessage::Text(text)) = message.data() {
if message.destination() == self.version_input_field
&& message.direction() == MessageDirection::FromWidget
{
if let Version::Specific(ref mut version) = self.selected_version {
*version = text.clone();
}
}
}
Some(self)
+13 -9
View File
@@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use cargo_metadata::Metadata;
use cargo_metadata::{Dependency, Metadata};
use fyrox::gui::utils::make_simple_tooltip;
use fyrox::{
asset::untyped::UntypedResource,
@@ -154,25 +154,29 @@ pub fn read_crate_metadata(manifest_path: &Path) -> Result<Metadata, String> {
}
}
pub fn fyrox_version(metadata: &Metadata) -> Option<String> {
pub fn fyrox_dependency(metadata: &Metadata) -> Option<&Dependency> {
for package in metadata.packages.iter() {
for dependency in package.dependencies.iter() {
if dependency.name == "fyrox" {
let version = dependency.req.to_string();
let pretty_version = version.replace('^', "");
let pretty_version = pretty_version.replace('+', "");
return Some(pretty_version);
return Some(dependency);
}
}
}
None
}
pub fn fyrox_version_or_default(manifest_path: &Path) -> String {
pub fn fyrox_version(metadata: &Metadata) -> Option<String> {
fyrox_dependency(metadata).map(|dependency| {
let version = dependency.req.to_string();
let pretty_version = version.replace('^', "");
pretty_version.replace('+', "")
})
}
pub fn fyrox_dependency_from_path(manifest_path: &Path) -> Option<Dependency> {
read_crate_metadata(manifest_path)
.ok()
.and_then(|metadata| fyrox_version(&metadata))
.unwrap_or_default()
.and_then(|metadata| fyrox_dependency(&metadata).cloned())
}
pub fn has_fyrox_in_deps(metadata: &Metadata) -> bool {
+63 -54
View File
@@ -37,9 +37,9 @@ use uuid::Uuid;
// However, it does not seem to work with builds published to crates.io, because when
// the template generator is published, it does not have these Cargo.toml's available
// and to solve this we just hard code these values and pray for the best.
const CURRENT_ENGINE_VERSION: &str = "0.34.0";
const CURRENT_EDITOR_VERSION: &str = "0.21.0";
const CURRENT_SCRIPTS_VERSION: &str = "0.3.0";
pub const CURRENT_ENGINE_VERSION: &str = "0.34.0";
pub const CURRENT_EDITOR_VERSION: &str = "0.21.0";
pub const CURRENT_SCRIPTS_VERSION: &str = "0.3.0";
fn write_file<P: AsRef<Path>, S: AsRef<str>>(path: P, content: S) -> Result<(), String> {
let mut file = File::create(path.as_ref()).map_err(|e| e.to_string())?;
@@ -780,74 +780,83 @@ pub fn upgrade_project(root_path: &Path, version: &str, local: bool) -> Result<(
// Open workspace manifest.
let workspace_manifest_path = root_path.join("Cargo.toml");
if let Ok(mut file) = File::open(&workspace_manifest_path) {
let mut toml = String::new();
if file.read_to_string(&mut toml).is_ok() {
drop(file);
match File::open(&workspace_manifest_path) {
Ok(mut file) => {
let mut toml = String::new();
if file.read_to_string(&mut toml).is_ok() {
drop(file);
if let Ok(mut document) = toml.parse::<DocumentMut>() {
if let Some(workspace) =
document.get_mut("workspace").and_then(|i| i.as_table_mut())
{
if let Some(dependencies) = workspace
.get_mut("dependencies")
.and_then(|i| i.as_table_mut())
if let Ok(mut document) = toml.parse::<DocumentMut>() {
if let Some(workspace) =
document.get_mut("workspace").and_then(|i| i.as_table_mut())
{
if version == "latest" {
if local {
let mut engine_table = table();
engine_table["path"] = value("../Fyrox/fyrox");
dependencies["fyrox"] = engine_table;
if let Some(dependencies) = workspace
.get_mut("dependencies")
.and_then(|i| i.as_table_mut())
{
if version == "latest" {
if local {
let mut engine_table = table();
engine_table["path"] = value("../Fyrox/fyrox");
dependencies["fyrox"] = engine_table;
let mut editor_table = table();
editor_table["path"] = value("../Fyrox/editor");
dependencies["fyroxed_base"] = editor_table;
let mut editor_table = table();
editor_table["path"] = value("../Fyrox/editor");
dependencies["fyroxed_base"] = editor_table;
if dependencies.contains_key("fyrox_scripts") {
let mut scripts_table = table();
scripts_table["path"] = value("../Fyrox/fyrox-scripts");
dependencies["fyrox_scripts"] = scripts_table;
}
} else {
dependencies["fyrox"] = value(CURRENT_ENGINE_VERSION);
dependencies["fyroxed_base"] = value(CURRENT_EDITOR_VERSION);
if dependencies.contains_key("fyrox_scripts") {
dependencies["fyrox_scripts"] = value(CURRENT_SCRIPTS_VERSION);
}
}
} else if version == "nightly" {
let mut table = table();
table["git"] = value("https://github.com/FyroxEngine/Fyrox");
dependencies["fyrox"] = table.clone();
dependencies["fyroxed_base"] = table.clone();
} else {
dependencies["fyrox"] = value(version);
if let Some((editor_version, scripts_version)) =
editor_versions.get(version)
{
dependencies["fyroxed_base"] = value(editor_version);
if let Some(scripts_version) = scripts_version {
if dependencies.contains_key("fyrox_scripts") {
dependencies["fyrox_scripts"] = value(scripts_version);
let mut scripts_table = table();
scripts_table["path"] = value("../Fyrox/fyrox-scripts");
dependencies["fyrox_scripts"] = scripts_table;
}
} else {
dependencies["fyrox"] = value(CURRENT_ENGINE_VERSION);
dependencies["fyroxed_base"] = value(CURRENT_EDITOR_VERSION);
if dependencies.contains_key("fyrox_scripts") {
dependencies["fyrox_scripts"] =
value(CURRENT_SCRIPTS_VERSION);
}
}
} else if version == "nightly" {
let mut table = table();
table["git"] = value("https://github.com/FyroxEngine/Fyrox");
dependencies["fyrox"] = table.clone();
dependencies["fyroxed_base"] = table.clone();
} else {
println!("WARNING: matching editor/scripts version not found!");
dependencies["fyrox"] = value(version);
if let Some((editor_version, scripts_version)) =
editor_versions.get(version)
{
dependencies["fyroxed_base"] = value(editor_version);
if let Some(scripts_version) = scripts_version {
if dependencies.contains_key("fyrox_scripts") {
dependencies["fyrox_scripts"] = value(scripts_version);
}
}
} else {
println!("WARNING: matching editor/scripts version not found!");
}
}
}
}
}
let mut file = File::create(workspace_manifest_path).map_err(|e| e.to_string())?;
file.write_all(document.to_string().as_bytes())
.map_err(|e| e.to_string())?;
let mut file =
File::create(&workspace_manifest_path).map_err(|e| e.to_string())?;
file.write_all(document.to_string().as_bytes())
.map_err(|e| e.to_string())?;
}
}
}
Err(err) => {
return Err(err.to_string());
}
}
Command::new("cargo")
.args(["update"])
.arg("update")
.arg("--manifest-path")
.arg(workspace_manifest_path)
.output()
.map_err(|e| e.to_string())?;