using CodeWalker.GameFiles; using CodeWalker.Project; using CodeWalker.Properties; using CodeWalker.World; using SharpDX; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace CodeWalker { public partial class ProjectForm : Form { WorldForm WorldForm; GameFileCache GameFileCache; RpfManager RpfMan; ProjectFile CurrentProjectFile; YmapFile CurrentYmapFile; YmapEntityDef CurrentEntity; YmapCarGen CurrentCarGen; YndFile CurrentYndFile; YndNode CurrentPathNode; YndLink CurrentPathLink; YnvFile CurrentYnvFile; YnvPoly CurrentNavPoly; TrainTrack CurrentTrainTrack; TrainTrackNode CurrentTrainNode; YmtFile CurrentScenario; ScenarioNode CurrentScenarioNode; MCScenarioChainingEdge CurrentScenarioChainEdge; bool renderentities = true; bool hidegtavmap = false; object ymapsyncroot = new object(); object yndsyncroot = new object(); object ynvsyncroot = new object(); object trainsyncroot = new object(); object scenariosyncroot = new object(); Dictionary visibleynds = new Dictionary(); Dictionary visibleynvs = new Dictionary(); Dictionary visibletrains = new Dictionary(); Dictionary visiblescenarios = new Dictionary(); bool populatingui = false; public bool IsProjectLoaded { get { return CurrentProjectFile != null; } } public ProjectForm(WorldForm worldForm) { InitializeComponent(); MainTabControl.TabPages.Remove(YnvTabPage);//TODO EntityTabControl.TabPages.Remove(EntityExtensionsTabPage);//TODO LoadDropDowns(); WorldForm = worldForm; if ((WorldForm != null) && (WorldForm.GameFileCache != null)) { GameFileCache = WorldForm.GameFileCache; RpfMan = GameFileCache.RpfMan; } else { GameFileCache = new GameFileCache(); new Thread(new ThreadStart(() => { GameFileCache.Init(UpdateStatus, UpdateStatus); RpfMan = GameFileCache.RpfMan; })).Start(); } } private void LoadDropDowns() { EntityLodLevelComboBox.Items.Clear(); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_ORPHANHD); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_HD); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_LOD); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD1); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD2); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD3); EntityLodLevelComboBox.Items.Add(Unk_1264241711.LODTYPES_DEPTH_SLOD4); EntityPriorityLevelComboBox.Items.Clear(); EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_REQUIRED); EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_OPTIONAL_HIGH); EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_OPTIONAL_MEDIUM); EntityPriorityLevelComboBox.Items.Add(Unk_648413703.PRI_OPTIONAL_LOW); } private void UpdateStatus(string text) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { UpdateStatus(text); })); } else { //TODO: status text //StatusLabel.Text = text; } } catch { } } private void UpdateFormTitleText() { if (CurrentProjectFile == null) { Text = "Project - CodeWalker by dexyfex"; } else { Text = CurrentProjectFile.Name + " - CodeWalker by dexyfex"; } } private void RefreshProjectUI() { bool enable = (CurrentProjectFile != null); FileCloseProjectMenu.Enabled = enable; FileSaveProjectMenu.Enabled = enable; FileSaveProjectAsMenu.Enabled = enable; } private void RefreshYmapUI() { bool enable = (CurrentYmapFile != null); bool inproj = YmapExistsInProject(CurrentYmapFile); YmapNewEntityMenu.Enabled = enable && inproj; YmapNewCarGenMenu.Enabled = enable && inproj; if (CurrentYmapFile != null) { YmapNameMenu.Text = "(" + CurrentYmapFile.Name + ")"; } else { YmapNameMenu.Text = "(No .ymap file selected)"; } YmapAddToProjectMenu.Enabled = enable && !inproj; YmapRemoveFromProjectMenu.Enabled = inproj; if (WorldForm != null) { WorldForm.EnableYmapUI(enable, CurrentYmapFile?.Name ?? ""); } } private void RefreshEntityUI() { bool enable = (CurrentEntity != null); bool isinproj = false; if (CurrentEntity != null) { isinproj = YmapExistsInProject(CurrentEntity.Ymap); } EntityAddToProjectButton.Enabled = !isinproj; EntityDeleteButton.Enabled = isinproj; } private void RefreshCarGenUI() { bool enable = (CurrentCarGen != null); bool isinproj = false; if (CurrentCarGen != null) { isinproj = YmapExistsInProject(CurrentCarGen.Ymap); } CarAddToProjectButton.Enabled = !isinproj; CarDeleteButton.Enabled = isinproj; } private void RefreshYndUI() { bool enable = (CurrentYndFile != null); bool inproj = YndExistsInProject(CurrentYndFile); YndNewNodeMenu.Enabled = enable && inproj; if (CurrentYndFile != null) { YndNameMenu.Text = "(" + CurrentYndFile.Name + ")"; } else { YndNameMenu.Text = "(No .ynd file selected)"; } YndAddToProjectMenu.Enabled = enable && !inproj; YndRemoveFromProjectMenu.Enabled = inproj; if (WorldForm != null) { WorldForm.EnableYndUI(enable, CurrentYndFile?.Name ?? ""); } } private void RefreshYnvUI() { bool enable = (CurrentYnvFile != null); bool inproj = YnvExistsInProject(CurrentYnvFile); YnvNewPolygonMenu.Enabled = enable && inproj; if (CurrentYnvFile != null) { YnvNameMenu.Text = "(" + CurrentYnvFile.Name + ")"; } else { YnvNameMenu.Text = "(No .ynv file selected)"; } YnvAddToProjectMenu.Enabled = enable && !inproj; YnvRemoveFromProjectMenu.Enabled = inproj; if (WorldForm != null) { WorldForm.EnableYnvUI(enable, CurrentYnvFile?.Name ?? ""); } } private void RefreshTrainTrackUI() { bool enable = (CurrentTrainTrack != null); bool inproj = TrainTrackExistsInProject(CurrentTrainTrack); TrainsNewNodeMenu.Enabled = enable && inproj; if (CurrentTrainTrack != null) { TrainsNameMenu.Text = "(" + CurrentTrainTrack.Name + ")"; } else { TrainsNameMenu.Text = "(No train track selected)"; } TrainsAddToProjectMenu.Enabled = enable && !inproj; TrainsRemoveFromProjectMenu.Enabled = inproj; if (WorldForm != null) { WorldForm.EnableTrainsUI(enable, CurrentTrainTrack?.Name ?? ""); } } private void RefreshScenarioUI() { bool enable = (CurrentScenario != null); bool inproj = ScenarioExistsInProject(CurrentScenario); ScenarioNewPointMenu.Enabled = enable && inproj; ScenarioNewPointFromSelectedMenu.Enabled = enable && inproj && (CurrentScenarioNode != null); ScenarioNewEntityOverrideMenu.Enabled = enable && inproj; ScenarioNewChainMenu.Enabled = enable && inproj; ScenarioNewClusterMenu.Enabled = enable && inproj; ScenarioImportChainMenu.Enabled = enable && inproj; if (CurrentScenario != null) { ScenarioNameMenu.Text = "(" + CurrentScenario.Name + ")"; } else { ScenarioNameMenu.Text = "(No scenario region selected)"; } ScenarioAddToProjectMenu.Enabled = enable && !inproj; ScenarioRemoveFromProjectMenu.Enabled = inproj; if (WorldForm != null) { WorldForm.EnableScenarioUI(enable, CurrentScenario?.Name ?? ""); } } private void RefreshUI() { RefreshYmapUI(); RefreshEntityUI(); RefreshCarGenUI(); RefreshYndUI(); RefreshYnvUI(); RefreshTrainTrackUI(); RefreshScenarioUI(); SetCurrentSaveItem(); LoadYmapTabPage(); LoadEntityTabPage(); LoadCarGenTabPage(); LoadYndTabPage(); LoadYnvTabPage(); LoadPathNodeTabPage(); LoadTrainTrackTabPage(); LoadTrainNodeTabPage(); LoadScenarioTabPage(); LoadScenarioNodeTabPages(); } private void SetCurrentSaveItem() { string filename = null; if (CurrentYmapFile != null) { filename = CurrentYmapFile.RpfFileEntry?.Name; } else if (CurrentYndFile != null) { filename = CurrentYndFile.RpfFileEntry?.Name; } else if (CurrentYnvFile != null) { filename = CurrentYnvFile.RpfFileEntry?.Name; } else if (CurrentTrainTrack != null) { filename = CurrentTrainTrack.RpfFileEntry?.Name; } else if (CurrentScenario != null) { filename = CurrentScenario.RpfFileEntry?.Name; } bool enable = !string.IsNullOrEmpty(filename); if (enable) { FileSaveItemMenu.Text = "Save " + filename; FileSaveItemAsMenu.Text = "Save " + filename + " As..."; } else { FileSaveItemMenu.Text = "Save"; FileSaveItemAsMenu.Text = "Save As..."; } FileSaveItemMenu.Tag = filename; FileSaveItemAsMenu.Tag = filename; FileSaveItemMenu.Enabled = enable; FileSaveItemMenu.Visible = enable; FileSaveItemAsMenu.Enabled = enable; FileSaveItemAsMenu.Visible = enable; if (WorldForm != null) { WorldForm.SetCurrentSaveItem(filename); } } public void Save() { if (CurrentYmapFile != null) { SaveYmap(); } else if (CurrentYndFile != null) { SaveYnd(); } else if (CurrentYnvFile != null) { SaveYnv(); } else if (CurrentTrainTrack != null) { SaveTrainTrack(); } else if (CurrentScenario != null) { SaveScenario(); } else if (CurrentProjectFile != null) { SaveProject(); } } public void SaveAll() { if (CurrentProjectFile != null) { if (CurrentProjectFile.YmapFiles != null) { var cymap = CurrentYmapFile; foreach (var ymap in CurrentProjectFile.YmapFiles) { CurrentYmapFile = ymap; SaveYmap(); } CurrentYmapFile = cymap; LoadYmapTabPage(); } if (CurrentProjectFile.YndFiles != null) { var cynd = CurrentYndFile; foreach (var ynd in CurrentProjectFile.YndFiles) { CurrentYndFile = ynd; SaveYnd(); } CurrentYndFile = cynd; LoadYndTabPage(); } if (CurrentProjectFile.YnvFiles != null) { var cynv = CurrentYnvFile; foreach (var ynv in CurrentProjectFile.YnvFiles) { CurrentYnvFile = ynv; SaveYnv(); } CurrentYnvFile = cynv; LoadYnvTabPage(); } if (CurrentProjectFile.TrainsFiles != null) { var ctrack = CurrentTrainTrack; foreach (var track in CurrentProjectFile.TrainsFiles) { CurrentTrainTrack = track; SaveYnd(); } CurrentTrainTrack = ctrack; LoadTrainTrackTabPage(); } if (CurrentProjectFile.ScenarioFiles != null) { var cscen = CurrentScenario; foreach (var scen in CurrentProjectFile.ScenarioFiles) { CurrentScenario = scen; SaveScenario(); } CurrentScenario = cscen; LoadScenarioTabPage(); } SaveProject(); } } private void SaveCurrentItem(bool saveas = false) { if (CurrentYmapFile != null) { SaveYmap(saveas); } else if (CurrentYndFile != null) { SaveYnd(saveas); } else if (CurrentYnvFile != null) { SaveYnv(saveas); } else if (CurrentTrainTrack != null) { SaveTrainTrack(saveas); } else if (CurrentScenario != null) { SaveScenario(saveas); } } public void NewProject() { if (CurrentProjectFile != null) { ////unload current project first CloseProject(); } CurrentProjectFile = new ProjectFile(); CurrentProjectFile.Name = "New CodeWalker Project"; CurrentProjectFile.Version = 1; CurrentProjectFile.HasChanged = true; LoadProjectUI(); } public void OpenProject() { string file = ShowOpenDialog("CodeWalker Projects|*.cwproj", string.Empty); if (string.IsNullOrEmpty(file)) { return; } CloseProject(); CurrentProjectFile = new ProjectFile(); CurrentProjectFile.Load(file); string cpath = new FileInfo(CurrentProjectFile.Filepath).Directory.FullName; foreach (var ymap in CurrentProjectFile.YmapFiles) { string filename = ymap.FilePath; if (!File.Exists(filename)) { filename = cpath + "\\" + filename; } if (File.Exists(filename)) { LoadYmapFromFile(ymap, filename); } else { MessageBox.Show("Couldn't find file: " + filename); } } foreach (var ynd in CurrentProjectFile.YndFiles) { string filename = ynd.FilePath; if (!File.Exists(filename)) { filename = cpath + "\\" + filename; } if (File.Exists(filename)) { LoadYndFromFile(ynd, filename); } else { MessageBox.Show("Couldn't find file: " + filename); } } foreach (var ynv in CurrentProjectFile.YnvFiles) { string filename = ynv.FilePath; if (!File.Exists(filename)) { filename = cpath + "\\" + filename; } if (File.Exists(filename)) { LoadYnvFromFile(ynv, filename); } else { MessageBox.Show("Couldn't find file: " + filename); } } foreach (var track in CurrentProjectFile.TrainsFiles) { string filename = track.FilePath; if (!File.Exists(filename)) { filename = cpath + "\\" + filename; } if (File.Exists(filename)) { LoadTrainTrackFromFile(track, filename); } else { MessageBox.Show("Couldn't find file: " + filename); } } foreach (var scenario in CurrentProjectFile.ScenarioFiles) { string filename = scenario.FilePath; if (!File.Exists(filename)) { filename = cpath + "\\" + filename; } if (File.Exists(filename)) { LoadScenarioFromFile(scenario, filename); } else { MessageBox.Show("Couldn't find file: " + filename); } } LoadProjectUI(); } public void SaveProject(bool saveas = false) { if (CurrentProjectFile == null) return; if (string.IsNullOrEmpty(CurrentProjectFile.Filepath) || saveas) { string fileName = ShowSaveDialog("CodeWalker Projects|*.cwproj", CurrentProjectFile.Filepath); if (string.IsNullOrEmpty(fileName)) { return; } //user cancelled string oldpath = CurrentProjectFile.Filepath; CurrentProjectFile.Filepath = fileName; CurrentProjectFile.Filename = new FileInfo(fileName).Name; CurrentProjectFile.UpdateFilenames(oldpath); } CurrentProjectFile.Save(); SetProjectHasChanged(false); } private void CloseProject() { if (CurrentProjectFile == null) return; foreach (var ymap in CurrentProjectFile.YmapFiles) { if ((ymap != null) && (ymap.HasChanged)) { //save the current ymap first? if (MessageBox.Show("Would you like to save "+ymap.Name+" before closing?", "Save .ymap before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) { CurrentYmapFile = ymap; SaveYmap(); } } } foreach (var ynd in CurrentProjectFile.YndFiles) { if ((ynd != null) && (ynd.HasChanged)) { //save the current ynd first? if (MessageBox.Show("Would you like to save " + ynd.Name + " before closing?", "Save .ynd before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) { CurrentYndFile = ynd; SaveYnd(); } } } foreach (var ynv in CurrentProjectFile.YnvFiles) { if ((ynv != null) && (ynv.HasChanged)) { //save the current ynv first? if (MessageBox.Show("Would you like to save " + ynv.Name + " before closing?", "Save .ynv before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) { CurrentYnvFile = ynv; SaveYnv(); } } } foreach (var trains in CurrentProjectFile.TrainsFiles) { if ((trains != null) && (trains.HasChanged)) { //save the current trains file first? if (MessageBox.Show("Would you like to save " + trains.Name + " before closing?", "Save trains file before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) { CurrentTrainTrack = trains; SaveTrainTrack(); } } } foreach (var scenario in CurrentProjectFile.ScenarioFiles) { if ((scenario != null) && (scenario.HasChanged)) { //save the current scenario file first? if (MessageBox.Show("Would you like to save " + scenario.Name + " before closing?", "Save scenario file before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) { CurrentScenario = scenario; SaveScenario(); } } } if (CurrentProjectFile.HasChanged) { //save the current project first? if (MessageBox.Show("Would you like to save the current project before closing?", "Save project before closing?", MessageBoxButtons.YesNo) == DialogResult.Yes) { SaveProject(); } } CurrentProjectFile = null; CurrentYmapFile = null; CurrentYndFile = null; LoadProjectUI(); if (WorldForm != null) { WorldForm.SelectItem(null);//make sure current selected item isn't still selected... } } private void LoadProjectUI() { RefreshProjectUI(); UpdateFormTitleText(); LoadProjectTree(); LoadProjectTabPage(); RefreshUI(); } private void LoadProjectTree() { ProjectTreeView.Nodes.Clear(); if (CurrentProjectFile == null) return; var pcstr = CurrentProjectFile.HasChanged ? "*" : ""; var projnode = ProjectTreeView.Nodes.Add(pcstr + CurrentProjectFile.Name); projnode.Tag = CurrentProjectFile; if (CurrentProjectFile.YmapFiles.Count > 0) { var ymapsnode = projnode.Nodes.Add("Ymap Files"); ymapsnode.Name = "Ymap"; foreach (var ymapfile in CurrentProjectFile.YmapFiles) { var ycstr = ymapfile.HasChanged ? "*" : ""; string name = ymapfile.Name; if (ymapfile.RpfFileEntry != null) { name = ymapfile.RpfFileEntry.Name; } var ymapnode = ymapsnode.Nodes.Add(ycstr + name); ymapnode.Tag = ymapfile; LoadYmapTreeNodes(ymapfile, ymapnode); JenkIndex.Ensure(name); JenkIndex.Ensure(Path.GetFileNameWithoutExtension(name)); } ymapsnode.Expand(); } if (CurrentProjectFile.YndFiles.Count > 0) { var yndsnode = projnode.Nodes.Add("Ynd Files"); yndsnode.Name = "Ynd"; foreach (var yndfile in CurrentProjectFile.YndFiles) { var ycstr = yndfile.HasChanged ? "*" : ""; string name = yndfile.Name; if (yndfile.RpfFileEntry != null) { name = yndfile.RpfFileEntry.Name; } var yndnode = yndsnode.Nodes.Add(ycstr + name); yndnode.Tag = yndfile; LoadYndTreeNodes(yndfile, yndnode); } yndsnode.Expand(); } if (CurrentProjectFile.YnvFiles.Count > 0) { var ynvsnode = projnode.Nodes.Add("Ynv Files"); ynvsnode.Name = "Ynv"; foreach (var ynvfile in CurrentProjectFile.YnvFiles) { var ycstr = ynvfile.HasChanged ? "*" : ""; string name = ynvfile.Name; if (ynvfile.RpfFileEntry != null) { name = ynvfile.RpfFileEntry.Name; } var ynvnode = ynvsnode.Nodes.Add(ycstr + name); ynvnode.Tag = ynvfile; LoadYnvTreeNodes(ynvfile, ynvnode); } ynvsnode.Expand(); } if (CurrentProjectFile.TrainsFiles.Count > 0) { var trainsnode = projnode.Nodes.Add("Trains Files"); trainsnode.Name = "Trains"; foreach (var trainfile in CurrentProjectFile.TrainsFiles) { var tcstr = trainfile.HasChanged ? "*" : ""; string name = trainfile.Name; if (trainfile.RpfFileEntry != null) { name = trainfile.RpfFileEntry.Name; } var trainnode = trainsnode.Nodes.Add(tcstr + name); trainnode.Tag = trainfile; LoadTrainTrackTreeNodes(trainfile, trainnode); } trainsnode.Expand(); } if (CurrentProjectFile.ScenarioFiles.Count > 0) { var scenariosnode = projnode.Nodes.Add("Scenario Files"); scenariosnode.Name = "Scenarios"; foreach (var scenariofile in CurrentProjectFile.ScenarioFiles) { var scstr = scenariofile.HasChanged ? "*" : ""; string name = scenariofile.Name; if (scenariofile.RpfFileEntry != null) { name = scenariofile.RpfFileEntry.Name; } var scenarionode = scenariosnode.Nodes.Add(scstr + name); scenarionode.Tag = scenariofile; LoadScenarioTreeNodes(scenariofile, scenarionode); } scenariosnode.Expand(); } projnode.Expand(); } private void LoadProjectTabPage() { if (CurrentProjectFile == null) { ProjectPanel.Enabled = false; ProjectNameTextBox.Text = ""; ProjectVersionLabel.Text = "Version: -"; } else { ProjectPanel.Enabled = true; ProjectNameTextBox.Text = CurrentProjectFile.Name; ProjectVersionLabel.Text = "Version: " + CurrentProjectFile.Version.ToString(); } } private void SetProjectHasChanged(bool changed) { if (CurrentProjectFile == null) return; CurrentProjectFile.HasChanged = changed; if (ProjectTreeView.Nodes.Count > 0) { //first node is the project... string changestr = changed ? "*" : ""; ProjectTreeView.Nodes[0].Text = changestr + CurrentProjectFile.Name; } UpdateFormTitleText(); } private void GenerateProjectManifest() { StringBuilder sb = new StringBuilder(); Dictionary deps = new Dictionary(); sb.AppendLine(""); sb.AppendLine(""); sb.AppendLine(" "); sb.AppendLine(" "); sb.AppendLine(" "); if ((CurrentProjectFile != null) && (CurrentProjectFile.YmapFiles.Count > 0)) { sb.AppendLine(" "); foreach (var ymap in CurrentProjectFile.YmapFiles) { var ymapname = ymap.RpfFileEntry?.NameLower; if (string.IsNullOrEmpty(ymapname)) { ymapname = ymap.Name.ToLowerInvariant(); } if (ymapname.EndsWith(".ymap")) { ymapname = ymapname.Substring(0, ymapname.Length - 5); } deps.Clear(); if (ymap.AllEntities != null) { foreach (var ent in ymap.AllEntities) { var ytyp = ent.Archetype?.Ytyp; if (ytyp != null) { var ytypname = ytyp.FileEntry?.NameLower; if (string.IsNullOrEmpty(ytypname)) { ytypname = ytyp.FileEntry?.Name?.ToLowerInvariant(); if (ytypname == null) ytypname = ""; } if (ytypname.EndsWith(".ytyp")) { ytypname = ytypname.Substring(0, ytypname.Length - 5); } deps[ytypname] = ytyp; } } } sb.AppendLine(" "); sb.AppendLine(" " + ymapname + ""); sb.AppendLine(" "); sb.AppendLine(" "); foreach (var kvp in deps) { sb.AppendLine(" " + kvp.Key + ""); } sb.AppendLine(" "); sb.AppendLine(" "); } sb.AppendLine(" "); } else { sb.AppendLine(" "); } sb.AppendLine(" "); sb.AppendLine(" "); sb.AppendLine(""); ProjectManifestTextBox.Text = sb.ToString(); } public void NewYmap() { if (CurrentProjectFile == null) { NewProject(); } if (CurrentProjectFile == null) return; int testi = 1; string fname = string.Empty; bool filenameok = false; while (!filenameok) { fname = "map" + testi.ToString() + ".ymap"; filenameok = !CurrentProjectFile.ContainsYmap(fname); testi++; } lock (ymapsyncroot) { YmapFile ymap = CurrentProjectFile.AddYmapFile(fname); if (ymap != null) { ymap.Loaded = true; ymap.HasChanged = true; //new ymap, flag as not saved ymap._CMapData.contentFlags = 65; //stream flags value } } CurrentProjectFile.HasChanged = true; LoadProjectTree(); } public void OpenYmap() { string[] files = ShowOpenDialogMulti("Ymap files|*.ymap", string.Empty); if (files == null) { return; } if (CurrentProjectFile == null) { NewProject(); } foreach (string file in files) { if (!File.Exists(file)) continue; var ymap = CurrentProjectFile.AddYmapFile(file); if (ymap != null) { SetProjectHasChanged(true); LoadYmapFromFile(ymap, file); LoadProjectTree(); } else { MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); } } } public void SaveYmap(bool saveas = false) { if (CurrentYmapFile == null) return; string ymapname = CurrentYmapFile.Name; string filepath = CurrentYmapFile.FilePath; if (string.IsNullOrEmpty(filepath)) { filepath = ymapname; } string origfile = filepath; if (!File.Exists(filepath)) { saveas = true; } byte[] data; lock (ymapsyncroot) //need to sync writes to ymap objects... { saveas = saveas || string.IsNullOrEmpty(filepath); if (saveas) { filepath = ShowSaveDialog("Ymap files|*.ymap", filepath); if (string.IsNullOrEmpty(filepath)) { return; } string newname = Path.GetFileNameWithoutExtension(filepath); JenkIndex.Ensure(newname); CurrentYmapFile.FilePath = filepath; CurrentYmapFile.RpfFileEntry.Name = new FileInfo(filepath).Name; CurrentYmapFile.Name = CurrentYmapFile.RpfFileEntry.Name; CurrentYmapFile._CMapData.name = new MetaHash(JenkHash.GenHash(newname)); } data = CurrentYmapFile.Save(); } if (data != null) { File.WriteAllBytes(filepath, data); } SetYmapHasChanged(false); if (saveas) { LoadYmapTabPage(); if (CurrentProjectFile != null) { //string newname = CurrentYmapFile.Name; string origpath = CurrentProjectFile.GetRelativePath(origfile); string newpath = CurrentProjectFile.GetRelativePath(CurrentYmapFile.FilePath); if (!CurrentProjectFile.RenameYmap(origpath, newpath)) { //couldn't rename it in the project? MessageBox.Show("Couldn't rename ymap in project! This shouldn't happen - check the project file XML."); } } SetProjectHasChanged(true); SetCurrentSaveItem(); } if (CurrentYmapFile.SaveWarnings != null) { string w = string.Join("\n", CurrentYmapFile.SaveWarnings); MessageBox.Show(CurrentYmapFile.SaveWarnings.Count.ToString() + " warnings were generated while saving the ymap:\n" + w); CurrentYmapFile.SaveWarnings = null;//clear it out for next time.. } } private void AddYmapToProject(YmapFile ymap) { if (ymap == null) return; if (CurrentProjectFile == null) { NewProject(); } if (YmapExistsInProject(ymap)) return; if (CurrentProjectFile.AddYmapFile(ymap)) { ymap.HasChanged = true; CurrentProjectFile.HasChanged = true; LoadProjectTree(); } CurrentYmapFile = ymap; RefreshUI(); if (CurrentEntity != null) { TrySelectEntityTreeNode(CurrentEntity); } else if (CurrentCarGen != null) { TrySelectCarGenTreeNode(CurrentCarGen); } } private void RemoveYmapFromProject() { if (CurrentYmapFile == null) return; if (CurrentProjectFile == null) return; CurrentProjectFile.RemoveYmapFile(CurrentYmapFile); CurrentYmapFile = null; LoadProjectTree(); RefreshUI(); } private void LoadYmapTabPage() { if (CurrentYmapFile == null) { YmapPanel.Enabled = false; YmapNameTextBox.Text = ""; YmapNameHashLabel.Text = "Hash: 0"; YmapParentTextBox.Text = string.Empty; YmapParentHashLabel.Text = "Hash: 0"; YmapFlagsTextBox.Text = string.Empty; YmapContentFlagsTextBox.Text = string.Empty; YmapCFlagsHDCheckBox.Checked = false; YmapCFlagsLODCheckBox.Checked = false; YmapCFlagsSLOD2CheckBox.Checked = false; YmapCFlagsInteriorCheckBox.Checked = false; YmapCFlagsSLODCheckBox.Checked = false; YmapCFlagsOcclusionCheckBox.Checked = false; YmapCFlagsPhysicsCheckBox.Checked = false; YmapCFlagsLODLightsCheckBox.Checked = false; YmapCFlagsDistLightsCheckBox.Checked = false; YmapCFlagsCriticalCheckBox.Checked = false; YmapCFlagsGrassCheckBox.Checked = false; YmapFlagsScriptedCheckBox.Checked = false; YmapFlagsLODCheckBox.Checked = false; YmapPhysicsDictionariesTextBox.Text = string.Empty; YmapEntitiesExtentsMinTextBox.Text = string.Empty; YmapEntitiesExtentsMaxTextBox.Text = string.Empty; YmapStreamingExtentsMinTextBox.Text = string.Empty; YmapStreamingExtentsMaxTextBox.Text = string.Empty; YmapFileLocationTextBox.Text = string.Empty; YmapProjectPathTextBox.Text = string.Empty; } else { populatingui = true; var md = CurrentYmapFile.CMapData; if (md.name.Hash == 0) { string name = Path.GetFileNameWithoutExtension(CurrentYmapFile.Name); JenkIndex.Ensure(name); md.name = new MetaHash(JenkHash.GenHash(name)); } YmapPanel.Enabled = true; YmapNameTextBox.Text = md.name.ToString(); YmapNameHashLabel.Text = "Hash: " + md.name.Hash.ToString(); YmapParentTextBox.Text = md.parent.ToString(); YmapParentHashLabel.Text = "Hash: " + md.parent.Hash.ToString(); YmapEntitiesExtentsMinTextBox.Text = FloatUtil.GetVector3String(md.entitiesExtentsMin); YmapEntitiesExtentsMaxTextBox.Text = FloatUtil.GetVector3String(md.entitiesExtentsMax); YmapStreamingExtentsMinTextBox.Text = FloatUtil.GetVector3String(md.streamingExtentsMin); YmapStreamingExtentsMaxTextBox.Text = FloatUtil.GetVector3String(md.streamingExtentsMax); YmapFileLocationTextBox.Text = CurrentYmapFile.FilePath; YmapProjectPathTextBox.Text = (CurrentProjectFile != null) ? CurrentProjectFile.GetRelativePath(CurrentYmapFile.FilePath) : CurrentYmapFile.FilePath; UpdateYmapFlagsUI(true, true); UpdateYmapPhysicsDictionariesUI(); populatingui = false; ////struct CMapData: //MetaHash name { get; set; } //8 8: Hash: 0: name //MetaHash parent { get; set; } //12 12: Hash: 0: parent //uint flags { get; set; } //16 16: UnsignedInt: 0: flags //uint contentFlags { get; set; } //20 20: UnsignedInt: 0: contentFlags//1785155637 //Vector3 streamingExtentsMin { get; set; } //32 32: Float_XYZ: 0: streamingExtentsMin//3710026271 //Vector3 streamingExtentsMax { get; set; } //48 48: Float_XYZ: 0: streamingExtentsMax//2720965429 //Vector3 entitiesExtentsMin { get; set; } //64 64: Float_XYZ: 0: entitiesExtentsMin//477478129 //Vector3 entitiesExtentsMax { get; set; } //80 80: Float_XYZ: 0: entitiesExtentsMax//1829192759 //Array_StructurePointer entities { get; set; } //96 96: Array: 0: entities {0: StructurePointer: 0: 256} //Array_Structure containerLods { get; set; } //112 112: Array: 0: containerLods//2935983381 {0: Structure: 372253349: 256} //Array_Structure boxOccluders { get; set; } //128 128: Array: 0: boxOccluders//3983590932 {0: Structure: SectionUNKNOWN7: 256} //Array_Structure occludeModels { get; set; } //144 144: Array: 0: occludeModels//2132383965 {0: Structure: SectionUNKNOWN5: 256} //Array_uint physicsDictionaries { get; set; } //160 160: Array: 0: physicsDictionaries//949589348 {0: Hash: 0: 256} //rage__fwInstancedMapData instancedData { get; set; } //176 176: Structure: rage__fwInstancedMapData: instancedData//2569067561 //Array_Structure timeCycleModifiers { get; set; } //224 224: Array: 0: timeCycleModifiers {0: Structure: CTimeCycleModifier: 256} //Array_Structure carGenerators { get; set; } //240 240: Array: 0: carGenerators//3254823756 {0: Structure: CCarGen: 256} //CLODLight LODLightsSOA { get; set; } //256 256: Structure: CLODLight: LODLightsSOA//1774371066 //CDistantLODLight DistantLODLightsSOA { get; set; } //392 392: Structure: CDistantLODLight: DistantLODLightsSOA//2954466641 //CBlockDesc block { get; set; } //440 440: Structure: CBlockDesc//3072355914: block } } private void LoadYmapFromFile(YmapFile ymap, string filename) { byte[] data = File.ReadAllBytes(filename); ymap.Load(data); GameFileCache.InitYmapEntityArchetypes(ymap); //this needs to be done after calling YmapFile.Load() } private void LoadYmapTreeNodes(YmapFile ymap, TreeNode node) { if (ymap == null) return; if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Entities and CarGens node.Nodes.Clear(); if ((ymap.AllEntities != null)&& (ymap.AllEntities.Length > 0)) { var entsnode = node.Nodes.Add("Entities (" + ymap.AllEntities.Length.ToString() + ")"); entsnode.Name = "Entities"; entsnode.Tag = ymap; var ents = ymap.AllEntities; for (int i = 0; i < ents.Length; i++) { var ent = ents[i]; var edef = ent.CEntityDef; var enode = entsnode.Nodes.Add(edef.archetypeName.ToString()); enode.Tag = ent; } } if ((ymap.CarGenerators != null) && (ymap.CarGenerators.Length > 0)) { var cargensnode = node.Nodes.Add("Car Generators (" + ymap.CarGenerators.Length.ToString() + ")"); cargensnode.Name = "CarGens"; cargensnode.Tag = ymap; var cargens = ymap.CarGenerators; for (int i = 0; i < cargens.Length; i++) { var cargen = cargens[i]; var ccgnode = cargensnode.Nodes.Add(cargen.ToString()); ccgnode.Tag = cargen; } } } private void SetYmapHasChanged(bool changed) { if (CurrentYmapFile == null) return; bool changechange = changed != CurrentYmapFile.HasChanged; if (!changechange) return; CurrentYmapFile.HasChanged = changed; SetYmapHasChangedUI(changed); } private void SetYmapHasChangedUI(bool changed) { if (ProjectTreeView.Nodes.Count > 0) { var pnode = ProjectTreeView.Nodes[0]; var ymnode = GetChildTreeNode(pnode, "Ymap"); if (ymnode == null) return; string changestr = changed ? "*" : ""; for (int i = 0; i < ymnode.Nodes.Count; i++) { var ynode = ymnode.Nodes[i]; if (ynode.Tag == CurrentYmapFile) { string name = CurrentYmapFile.Name; if (CurrentYmapFile.RpfFileEntry != null) { name = CurrentYmapFile.RpfFileEntry.Name; } ynode.Text = changestr + name; break; } } } } private void UpdateYmapFlagsUI(bool updateCheckboxes, bool updateTextboxes) { if (CurrentYmapFile == null) return; var md = CurrentYmapFile.CMapData; var flags = md.flags; var contentFlags = md.contentFlags; if (updateCheckboxes) { YmapCFlagsHDCheckBox.Checked = IsBitSet(contentFlags, 0); //1 YmapCFlagsLODCheckBox.Checked = IsBitSet(contentFlags, 1); //2 YmapCFlagsSLOD2CheckBox.Checked = IsBitSet(contentFlags, 2); //4 YmapCFlagsInteriorCheckBox.Checked = IsBitSet(contentFlags, 3); //8 YmapCFlagsSLODCheckBox.Checked = IsBitSet(contentFlags, 4); //16 YmapCFlagsOcclusionCheckBox.Checked = IsBitSet(contentFlags, 5); //32 YmapCFlagsPhysicsCheckBox.Checked = IsBitSet(contentFlags, 6); //64 YmapCFlagsLODLightsCheckBox.Checked = IsBitSet(contentFlags, 7); //128 YmapCFlagsDistLightsCheckBox.Checked = IsBitSet(contentFlags, 8); //256 YmapCFlagsCriticalCheckBox.Checked = IsBitSet(contentFlags, 9); //512 YmapCFlagsGrassCheckBox.Checked = IsBitSet(contentFlags, 10); //1024 YmapFlagsScriptedCheckBox.Checked = IsBitSet(flags, 0); //1 YmapFlagsLODCheckBox.Checked = IsBitSet(flags, 1); //2 } if (updateTextboxes) { YmapFlagsTextBox.Text = flags.ToString(); YmapContentFlagsTextBox.Text = contentFlags.ToString(); } } private void SetYmapFlagsFromCheckBoxes() { if (populatingui) return; if (CurrentYmapFile == null) return; uint flags = 0; uint contentFlags = 0; contentFlags = UpdateBit(contentFlags, 0, YmapCFlagsHDCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 1, YmapCFlagsLODCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 2, YmapCFlagsSLOD2CheckBox.Checked); contentFlags = UpdateBit(contentFlags, 3, YmapCFlagsInteriorCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 4, YmapCFlagsSLODCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 5, YmapCFlagsOcclusionCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 6, YmapCFlagsPhysicsCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 7, YmapCFlagsLODLightsCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 8, YmapCFlagsDistLightsCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 9, YmapCFlagsCriticalCheckBox.Checked); contentFlags = UpdateBit(contentFlags, 10, YmapCFlagsGrassCheckBox.Checked); flags = UpdateBit(flags, 0, YmapFlagsScriptedCheckBox.Checked); flags = UpdateBit(flags, 1, YmapFlagsLODCheckBox.Checked); lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.flags != flags) { CurrentYmapFile._CMapData.flags = flags; SetYmapHasChanged(true); } if (CurrentYmapFile._CMapData.contentFlags != contentFlags) { CurrentYmapFile._CMapData.contentFlags = contentFlags; SetYmapHasChanged(true); } } populatingui = true; UpdateYmapFlagsUI(false, true); //update textbox populatingui = false; } private void SetYmapFlagsFromTextBoxes() { if (populatingui) return; if (CurrentYmapFile == null) return; uint flags = 0; uint contentFlags = 0; uint.TryParse(YmapFlagsTextBox.Text, out flags); uint.TryParse(YmapContentFlagsTextBox.Text, out contentFlags); lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.flags != flags) { CurrentYmapFile._CMapData.flags = flags; SetYmapHasChanged(true); } if (CurrentYmapFile._CMapData.contentFlags != contentFlags) { CurrentYmapFile._CMapData.contentFlags = contentFlags; SetYmapHasChanged(true); } } populatingui = true; UpdateYmapFlagsUI(true, false); //update checkboxes populatingui = false; } private void CalcYmapFlags() { if (populatingui) return; if (CurrentYmapFile == null) return; lock (ymapsyncroot) { if (CurrentYmapFile.CalcFlags()) { SetYmapHasChanged(true); } } populatingui = true; UpdateYmapFlagsUI(true, true); //update checkboxes and textboxes populatingui = false; } private void CalcYmapExtents() { if (CurrentYmapFile == null) return; var allents = CurrentYmapFile.AllEntities; var allbatches = CurrentYmapFile.GrassInstanceBatches; if ((allents == null) && (allbatches == null)) { MessageBox.Show("No items to calculate extents from."); return; } lock (ymapsyncroot) { if (CurrentYmapFile.CalcExtents()) { SetYmapHasChanged(true); } } populatingui = true; var md = CurrentYmapFile.CMapData; YmapEntitiesExtentsMinTextBox.Text = FloatUtil.GetVector3String(md.entitiesExtentsMin); YmapEntitiesExtentsMaxTextBox.Text = FloatUtil.GetVector3String(md.entitiesExtentsMax); YmapStreamingExtentsMinTextBox.Text = FloatUtil.GetVector3String(md.streamingExtentsMin); YmapStreamingExtentsMaxTextBox.Text = FloatUtil.GetVector3String(md.streamingExtentsMax); populatingui = false; } private void UpdateYmapPhysicsDictionariesUI() { if ((CurrentYmapFile == null) || (CurrentYmapFile.physicsDictionaries == null)) { YmapPhysicsDictionariesTextBox.Text = string.Empty; } else { StringBuilder sb = new StringBuilder(); foreach (var hash in CurrentYmapFile.physicsDictionaries) { sb.AppendLine(hash.ToString()); } YmapPhysicsDictionariesTextBox.Text = sb.ToString(); } } private void SetYmapPhysicsDictionariesFromTextbox() { if (populatingui) return; if (CurrentYmapFile == null) return; List hashes = new List(); var strs = YmapPhysicsDictionariesTextBox.Text.Split('\n'); foreach (var str in strs) { var tstr = str.Trim(); if (!string.IsNullOrEmpty(tstr)) { uint h = 0; if (uint.TryParse(tstr, out h)) { hashes.Add(h); } else { h = JenkHash.GenHash(tstr.ToLowerInvariant()); hashes.Add(h); } } } lock (ymapsyncroot) { CurrentYmapFile.physicsDictionaries = (hashes.Count > 0) ? hashes.ToArray() : null; SetYmapHasChanged(true); } } private Vector3 GetSpawnPos(float dist) { Vector3 pos = Vector3.Zero; if (WorldForm != null) { Vector3 campos = WorldForm.GetCameraPosition(); Vector3 camdir = WorldForm.GetCameraViewDir(); pos = campos + camdir * dist; } return pos; } public void NewEntity(YmapEntityDef copy = null, bool copyPosition = false) { if (CurrentYmapFile == null) return; float spawndist = 5.0f; //use archetype BSradius if starting with a copy... if (copy != null) { spawndist = copy.BSRadius * 2.5f; } bool cp = copyPosition && (copy != null); Vector3 pos = cp ? copy.Position : GetSpawnPos(spawndist); CEntityDef cent = new CEntityDef(); if (copy != null) { cent = copy.CEntityDef; //TODO: copy entity extensions! } else { cent.archetypeName = new MetaHash(JenkHash.GenHash("prop_alien_egg_01")); cent.rotation = new Vector4(0, 0, 0, 1); cent.scaleXY = 1.0f; cent.scaleZ = 1.0f; cent.flags = 1572872; cent.parentIndex = -1; cent.lodDist = 200.0f; cent.lodLevel = Unk_1264241711.LODTYPES_DEPTH_ORPHANHD; cent.priorityLevel = Unk_648413703.PRI_REQUIRED; cent.ambientOcclusionMultiplier = 255; cent.artificialAmbientOcclusion = 255; } cent.position = pos; YmapEntityDef ent = new YmapEntityDef(CurrentYmapFile, 0, ref cent); ent.SetArchetype(GameFileCache.GetArchetype(cent.archetypeName)); if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { CurrentYmapFile.AddEntity(ent); } } else { CurrentYmapFile.AddEntity(ent); } LoadProjectTree(); TrySelectEntityTreeNode(ent); CurrentEntity = ent; LoadEntityTabPage(); } public bool DeleteEntity() { if (CurrentYmapFile == null) return false; if (CurrentEntity == null) return false; if (CurrentEntity.Ymap != CurrentYmapFile) return false; if (CurrentYmapFile.AllEntities == null) return false; //nothing to delete.. if (CurrentYmapFile.RootEntities == null) return false; //nothing to delete.. if (CurrentEntity._CEntityDef.numChildren != 0) { MessageBox.Show("This entity's numChildren is not 0 - deleting entities with children is not currently supported by CodeWalker."); return true; } int idx = CurrentEntity.Index; for (int i = idx + 1; i < CurrentYmapFile.AllEntities.Length; i++) { var ent = CurrentYmapFile.AllEntities[i]; if (ent._CEntityDef.numChildren != 0) { MessageBox.Show("There are other entities present in this .ymap that have children. Deleting this entity is not currently supported by CodeWalker."); return true; } } if (MessageBox.Show("Are you sure you want to delete this entity?\n" + CurrentEntity._CEntityDef.archetypeName.ToString() + "\n" + CurrentEntity.Position.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return true; } //find this now to remove it later. var tn = FindEntityTreeNode(CurrentEntity); bool res = false; if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { res = CurrentYmapFile.RemoveEntity(CurrentEntity); //WorldForm.SelectItem(null, null, null); } } else { res = CurrentYmapFile.RemoveEntity(CurrentEntity); } if (!res) { MessageBox.Show("Entity.Index didn't match the index of the entity in the ymap. This shouldn't happen, check LOD linkages!"); } SetYmapHasChangedUI(true); CurrentEntity = null; if ((tn != null) && (tn.Parent != null)) { tn.Parent.Text = "Entities (" + CurrentYmapFile.AllEntities.Length.ToString() + ")"; tn.Parent.Nodes.Remove(tn); } else { //no need for this when removing the node above will select something else. LoadEntityTabPage(); //this case really shouldn't happen... } return true; } private void AddEntityToProject() { if (CurrentEntity == null) return; if (CurrentEntity.Ymap == null) { MessageBox.Show("Sorry, interior entities cannot currently be added to the project."); return; } CurrentYmapFile = CurrentEntity.Ymap; if (!YmapExistsInProject(CurrentYmapFile)) { var ent = CurrentEntity; CurrentYmapFile.HasChanged = true; AddYmapToProject(CurrentYmapFile); CurrentEntity = ent; //bug fix for some reason the treeview selects the project node here. CurrentYmapFile = ent.Ymap; TrySelectEntityTreeNode(ent); } } private void LoadEntityTabPage() { if (CurrentEntity == null) { EntityPanel.Enabled = false; EntityArchetypeTextBox.Text = string.Empty; EntityArchetypeHashLabel.Text = "Hash: 0"; EntityFlagsTextBox.Text = string.Empty; EntityGuidTextBox.Text = string.Empty; EntityPositionTextBox.Text = string.Empty; EntityRotationTextBox.Text = string.Empty; EntityScaleXYTextBox.Text = string.Empty; EntityScaleZTextBox.Text = string.Empty; EntityParentIndexTextBox.Text = string.Empty; EntityLodDistTextBox.Text = string.Empty; EntityChildLodDistTextBox.Text = string.Empty; EntityLodLevelComboBox.SelectedIndex = 0;// Math.Max(EntityLodLevelComboBox.FindString(), 0); EntityNumChildrenTextBox.Text = string.Empty; EntityPriorityLevelComboBox.SelectedIndex = 0; //Math.Max(.. EntityAOMultiplierTextBox.Text = string.Empty; EntityArtificialAOTextBox.Text = string.Empty; EntityTintValueTextBox.Text = string.Empty; EntityPivotEditCheckBox.Checked = false; EntityPivotPositionTextBox.Text = string.Empty; EntityPivotRotationTextBox.Text = string.Empty; foreach (int i in EntityFlagsCheckedListBox.CheckedIndices) { EntityFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); } } else { populatingui = true; var e = CurrentEntity.CEntityDef; var po = CurrentEntity.PivotOrientation; EntityPanel.Enabled = true; EntityArchetypeTextBox.Text = e.archetypeName.ToString(); EntityArchetypeHashLabel.Text = "Hash: " + e.archetypeName.Hash.ToString(); EntityFlagsTextBox.Text = e.flags.ToString(); EntityGuidTextBox.Text = e.guid.ToString(); EntityPositionTextBox.Text = FloatUtil.GetVector3String(e.position); EntityRotationTextBox.Text = FloatUtil.GetVector4String(e.rotation); EntityScaleXYTextBox.Text = FloatUtil.ToString(e.scaleXY); EntityScaleZTextBox.Text = FloatUtil.ToString(e.scaleZ); EntityParentIndexTextBox.Text = e.parentIndex.ToString(); EntityLodDistTextBox.Text = FloatUtil.ToString(e.lodDist); EntityChildLodDistTextBox.Text = FloatUtil.ToString(e.childLodDist); EntityLodLevelComboBox.SelectedIndex = Math.Max(EntityLodLevelComboBox.FindString(e.lodLevel.ToString()), 0); EntityNumChildrenTextBox.Text = e.numChildren.ToString(); EntityPriorityLevelComboBox.SelectedIndex = Math.Max(EntityPriorityLevelComboBox.FindString(e.priorityLevel.ToString()), 0); EntityAOMultiplierTextBox.Text = e.ambientOcclusionMultiplier.ToString(); EntityArtificialAOTextBox.Text = e.artificialAmbientOcclusion.ToString(); EntityTintValueTextBox.Text = e.tintValue.ToString(); EntityPivotPositionTextBox.Text = FloatUtil.GetVector3String(CurrentEntity.PivotPosition); EntityPivotRotationTextBox.Text = FloatUtil.GetVector4String(new Vector4(po.X, po.Y, po.Z, po.W)); for (int i = 0; i < EntityFlagsCheckedListBox.Items.Count; i++) { var cv = ((e.flags & (1u << i)) > 0); EntityFlagsCheckedListBox.SetItemCheckState(i, cv ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; if (WorldForm != null) { WorldForm.SelectEntity(CurrentEntity); //hopefully the drawable is already loaded - this will try get from cache } ////struct CEntityDef: //MetaHash archetypeName { get; set; } //8 8: Hash: 0: archetypeName //uint flags { get; set; } //12 12: UnsignedInt: 0: flags //uint guid { get; set; } //16 16: UnsignedInt: 0: guid //Vector3 position { get; set; } //32 32: Float_XYZ: 0: position //Vector4 rotation { get; set; } //48 48: Float_XYZW: 0: rotation //float scaleXY { get; set; } //64 64: Float: 0: 2627937847 //float scaleZ { get; set; } //68 68: Float: 0: 284916802 //int parentIndex { get; set; } //72 72: SignedInt: 0: parentIndex //float lodDist { get; set; } //76 76: Float: 0: lodDist //float childLodDist { get; set; } //80 80: Float: 0: childLodDist//3398912973 //Unk_1264241711 lodLevel { get; set; } //84 84: IntEnum: 1264241711: lodLevel //LODTYPES_DEPTH_ //uint numChildren { get; set; } //88 88: UnsignedInt: 0: numChildren//2793909385 //Unk_648413703 priorityLevel { get; set; } //92 92: IntEnum: 648413703: priorityLevel//647098393 //Array_StructurePointer extensions { get; set; } //96 96: Array: 0: extensions {0: StructurePointer: 0: 256} //int ambientOcclusionMultiplier { get; set; } //112 112: SignedInt: 0: ambientOcclusionMultiplier//415356295 //int artificialAmbientOcclusion { get; set; } //116 116: SignedInt: 0: artificialAmbientOcclusion//599844163 //uint tintValue { get; set; } //120 120: UnsignedInt: 0: tintValue//1015358759 } } public bool IsCurrentEntity(YmapEntityDef ent) { return CurrentEntity == ent; } public void NewCarGen(YmapCarGen copy = null, bool copyPosition = false) { if (CurrentYmapFile == null) return; Vector3 pos = GetSpawnPos(10.0f); CCarGen ccg = new CCarGen(); if (copy != null) { ccg = copy.CCarGen; } else { ccg.flags = 3680; ccg.orientX = 5.0f; ccg.perpendicularLength = 2.6f; //TODO: set default values for cargen } if (!copyPosition || (copy == null)) { ccg.position = pos; } YmapCarGen cg = new YmapCarGen(CurrentYmapFile, ccg); if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { CurrentYmapFile.AddCarGen(cg); } } else { CurrentYmapFile.AddCarGen(cg); } LoadProjectTree(); TrySelectCarGenTreeNode(cg); CurrentCarGen = cg; LoadCarGenTabPage(); } public bool DeleteCarGen() { if (CurrentYmapFile == null) return false; if (CurrentCarGen == null) return false; if (CurrentCarGen.Ymap != CurrentYmapFile) return false; if (CurrentYmapFile.CarGenerators == null) return false; //nothing to delete.. if (MessageBox.Show("Are you sure you want to delete this car generator?\n" + CurrentCarGen.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return true; } //find this now to remove it later. var tn = FindCarGenTreeNode(CurrentCarGen); bool res = false; if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { res = CurrentYmapFile.RemoveCarGen(CurrentCarGen); //WorldForm.SelectItem(null, null, null); } } else { res = CurrentYmapFile.RemoveCarGen(CurrentCarGen); } if (!res) { MessageBox.Show("Unable to delete the car generator. This shouldn't happen!"); } SetYmapHasChangedUI(true); CurrentCarGen = null; if ((tn != null) && (tn.Parent != null)) { tn.Parent.Text = "Car Generators (" + CurrentYmapFile.CarGenerators.Length.ToString() + ")"; tn.Parent.Nodes.Remove(tn); } else { //no need for this when removing the node above will select something else. LoadCarGenTabPage(); //this case really shouldn't happen... } return true; } private void AddCarGenToProject() { if (CurrentCarGen == null) return; CurrentYmapFile = CurrentCarGen.Ymap; if (!YmapExistsInProject(CurrentYmapFile)) { var cargen = CurrentCarGen; CurrentYmapFile.HasChanged = true; AddYmapToProject(CurrentYmapFile); CurrentCarGen = cargen; //bug fix for some reason the treeview selects the project node here. CurrentYmapFile = cargen.Ymap; TrySelectCarGenTreeNode(cargen); } } private void LoadCarGenTabPage() { if (CurrentCarGen == null) { CarGenPanel.Enabled = false; CarModelTextBox.Text = string.Empty; CarModelHashLabel.Text = "Hash: 0"; CarPopGroupTextBox.Text = string.Empty; CarPopGroupHashLabel.Text = "Hash: 0"; CarFlagsTextBox.Text = string.Empty; CarPositionTextBox.Text = string.Empty; CarOrientXTextBox.Text = string.Empty; CarOrientYTextBox.Text = string.Empty; CarPerpendicularLengthTextBox.Text = string.Empty; CarBodyColorRemap1TextBox.Text = string.Empty; CarBodyColorRemap2TextBox.Text = string.Empty; CarBodyColorRemap3TextBox.Text = string.Empty; CarBodyColorRemap4TextBox.Text = string.Empty; CarLiveryTextBox.Text = string.Empty; foreach (int i in CarFlagsCheckedListBox.CheckedIndices) { CarFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); } } else { populatingui = true; var c = CurrentCarGen.CCarGen; CarGenPanel.Enabled = true; CarModelTextBox.Text = c.carModel.ToString(); CarModelHashLabel.Text = "Hash: " + c.carModel.Hash.ToString(); CarPopGroupTextBox.Text = c.popGroup.ToString(); CarPopGroupHashLabel.Text = "Hash: " + c.popGroup.Hash.ToString(); CarFlagsTextBox.Text = c.flags.ToString(); CarPositionTextBox.Text = FloatUtil.GetVector3String(c.position); CarOrientXTextBox.Text = FloatUtil.ToString(c.orientX); CarOrientYTextBox.Text = FloatUtil.ToString(c.orientY); CarPerpendicularLengthTextBox.Text = FloatUtil.ToString(c.perpendicularLength); CarBodyColorRemap1TextBox.Text = c.bodyColorRemap1.ToString(); CarBodyColorRemap2TextBox.Text = c.bodyColorRemap2.ToString(); CarBodyColorRemap3TextBox.Text = c.bodyColorRemap3.ToString(); CarBodyColorRemap4TextBox.Text = c.bodyColorRemap4.ToString(); CarLiveryTextBox.Text = c.livery.ToString(); for (int i = 0; i < CarFlagsCheckedListBox.Items.Count; i++) { var cv = ((c.flags & (1u << i)) > 0); CarFlagsCheckedListBox.SetItemCheckState(i, cv ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; if (WorldForm != null) { WorldForm.SelectCarGen(CurrentCarGen); } ////struct CCarGen: //Vector3 position { get; set; } //16 16: Float_XYZ: 0: position //float orientX { get; set; } //32 32: Float: 0: orientX=735213009 //float orientY { get; set; } //36 36: Float: 0: orientY=979440342 //float perpendicularLength { get; set; } //40 40: Float: 0: perpendicularLength=124715667 //MetaHash carModel { get; set; } //44 44: Hash: 0: carModel //uint flags { get; set; } //48 48: UnsignedInt: 0: flags //int bodyColorRemap1 { get; set; } //52 52: SignedInt: 0: bodyColorRemap1=1429703670 //int bodyColorRemap2 { get; set; } //56 56: SignedInt: 0: bodyColorRemap2=1254848286 //int bodyColorRemap3 { get; set; } //60 60: SignedInt: 0: bodyColorRemap3=1880965569 //int bodyColorRemap4 { get; set; } //64 64: SignedInt: 0: bodyColorRemap4=1719152247 //MetaHash popGroup { get; set; } //68 68: Hash: 0: popGroup=911358791 //sbyte livery { get; set; } //72 72: SignedByte: 0: livery } } public bool IsCurrentCarGen(YmapCarGen cargen) { return CurrentCarGen == cargen; } public void NewYnd() { if (CurrentProjectFile == null) { NewProject(); } if (CurrentProjectFile == null) return; int testi = 1; string fname = string.Empty; bool filenameok = false; while (!filenameok) { fname = "nodes" + testi.ToString() + ".ynd"; filenameok = !CurrentProjectFile.ContainsYnd(fname); testi++; } lock (yndsyncroot) { YndFile ynd = CurrentProjectFile.AddYndFile(fname); if (ynd != null) { ynd.Loaded = true; ynd.HasChanged = true; //new ynd, flag as not saved //TODO: set new ynd default values... ynd.NodeDictionary = new NodeDictionary(); } } CurrentProjectFile.HasChanged = true; LoadProjectTree(); } public void OpenYnd() { string[] files = ShowOpenDialogMulti("Ynd files|*.ynd", string.Empty); if (files == null) { return; } if (CurrentProjectFile == null) { NewProject(); } foreach (string file in files) { if (!File.Exists(file)) continue; var ynd = CurrentProjectFile.AddYndFile(file); if (ynd != null) { SetProjectHasChanged(true); LoadYndFromFile(ynd, file); LoadProjectTree(); } else { MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); } } } public void SaveYnd(bool saveas = false) { if ((CurrentYndFile == null) && (CurrentPathNode != null)) CurrentYndFile = CurrentPathNode.Ynd; if (CurrentYndFile == null) return; string yndname = CurrentYndFile.Name; string filepath = CurrentYndFile.FilePath; if (string.IsNullOrEmpty(filepath)) { filepath = yndname; } string origfile = filepath; if (!File.Exists(filepath)) { saveas = true; } byte[] data; lock (yndsyncroot) //need to sync writes to ynd objects... { saveas = saveas || string.IsNullOrEmpty(filepath); if (saveas) { filepath = ShowSaveDialog("Ynd files|*.ynd", filepath); if (string.IsNullOrEmpty(filepath)) { return; } string newname = Path.GetFileNameWithoutExtension(filepath); JenkIndex.Ensure(newname); CurrentYndFile.FilePath = filepath; CurrentYndFile.RpfFileEntry.Name = new FileInfo(filepath).Name; CurrentYndFile.Name = CurrentYndFile.RpfFileEntry.Name; } data = CurrentYndFile.Save(); } if (data != null) { File.WriteAllBytes(filepath, data); } SetYndHasChanged(false); if (saveas) { LoadYndTabPage(); if (CurrentProjectFile != null) { string origpath = CurrentProjectFile.GetRelativePath(origfile); string newpath = CurrentProjectFile.GetRelativePath(CurrentYndFile.FilePath); if (!CurrentProjectFile.RenameYnd(origpath, newpath)) { //couldn't rename it in the project? happens when project not saved yet... //MessageBox.Show("Couldn't rename ynd in project! This shouldn't happen - check the project file XML."); } } SetProjectHasChanged(true); SetCurrentSaveItem(); } } private void AddYndToProject(YndFile ynd) { if (ynd == null) return; if (CurrentProjectFile == null) { NewProject(); } if (YndExistsInProject(ynd)) return; if (CurrentProjectFile.AddYndFile(ynd)) { ynd.HasChanged = true; CurrentProjectFile.HasChanged = true; LoadProjectTree(); } CurrentYndFile = ynd; RefreshUI(); if (CurrentPathNode != null) { TrySelectPathNodeTreeNode(CurrentPathNode); } } private void RemoveYndFromProject() { if (CurrentYndFile == null) return; if (CurrentProjectFile == null) return; CurrentProjectFile.RemoveYndFile(CurrentYndFile); CurrentYndFile = null; LoadProjectTree(); RefreshUI(); } private void LoadYndTabPage() { if (CurrentYndFile == null) { YndPanel.Enabled = false; YndRpfPathTextBox.Text = string.Empty; YndFilePathTextBox.Text = string.Empty; YndProjectPathTextBox.Text = string.Empty; YndAreaIDXUpDown.Value = 0; YndAreaIDYUpDown.Value = 0; YndAreaIDInfoLabel.Text = "ID: 0"; YndTotalNodesLabel.Text = "Total Nodes: 0"; YndVehicleNodesUpDown.Value = 0; YndVehicleNodesUpDown.Maximum = 0; YndPedNodesUpDown.Value = 0; YndPedNodesUpDown.Maximum = 0; } else { populatingui = true; var nd = CurrentYndFile.NodeDictionary; YndPanel.Enabled = true; YndRpfPathTextBox.Text = CurrentYndFile.RpfFileEntry.Path; YndFilePathTextBox.Text = CurrentYndFile.FilePath; YndProjectPathTextBox.Text = (CurrentProjectFile != null) ? CurrentProjectFile.GetRelativePath(CurrentYndFile.FilePath) : CurrentYndFile.FilePath; YndAreaIDXUpDown.Value = CurrentYndFile.CellX; YndAreaIDYUpDown.Value = CurrentYndFile.CellY; YndAreaIDInfoLabel.Text = "ID: " + CurrentYndFile.AreaID.ToString(); YndTotalNodesLabel.Text = "Total Nodes: " + (nd?.NodesCount.ToString()??"0"); YndVehicleNodesUpDown.Maximum = nd?.NodesCount??0; YndVehicleNodesUpDown.Value = Math.Min(nd?.NodesCountVehicle??0, YndVehicleNodesUpDown.Maximum); YndPedNodesUpDown.Maximum = nd?.NodesCount??0; YndPedNodesUpDown.Value = Math.Min(nd?.NodesCountPed??0, YndPedNodesUpDown.Maximum); populatingui = false; } } private void LoadYndFromFile(YndFile ynd, string filename) { byte[] data = File.ReadAllBytes(filename); ynd.Load(data); if (WorldForm != null) { WorldForm.UpdatePathYndGraphics(ynd, true); //links don't get drawn until something changes otherwise //note: this is actually necessary to properly populate junctions data........ } } private void LoadYndTreeNodes(YndFile ynd, TreeNode node) { if (ynd == null) return; if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Nodes node.Nodes.Clear(); if ((ynd.Nodes != null) && (ynd.Nodes.Length > 0)) { var nodesnode = node.Nodes.Add("Nodes (" + ynd.Nodes.Length.ToString() + ")"); nodesnode.Name = "Nodes"; nodesnode.Tag = ynd; var nodes = ynd.Nodes; for (int i = 0; i < nodes.Length; i++) { var ynode = nodes[i]; var nnode = ynode.RawData; var tnode = nodesnode.Nodes.Add(nnode.ToString()); tnode.Tag = ynode; } } } private void SetYndHasChanged(bool changed) { if (CurrentYndFile == null) return; bool changechange = changed != CurrentYndFile.HasChanged; if (!changechange) return; CurrentYndFile.HasChanged = changed; SetYndHasChangedUI(changed); } private void SetYndHasChangedUI(bool changed) { if (ProjectTreeView.Nodes.Count > 0) { var pnode = ProjectTreeView.Nodes[0]; var ynnode = GetChildTreeNode(pnode, "Ynd"); if (ynnode == null) return; string changestr = changed ? "*" : ""; for (int i = 0; i < ynnode.Nodes.Count; i++) { var ynode = ynnode.Nodes[i]; if (ynode.Tag == CurrentYndFile) { string name = CurrentYndFile.Name; if (CurrentYndFile.RpfFileEntry != null) { name = CurrentYndFile.RpfFileEntry.Name; } ynode.Text = changestr + name; break; } } } } public void NewPathNode(YndNode copy = null, bool copyPosition = false) { if (CurrentYndFile == null) return; var n = CurrentYndFile.AddNode(); var areaid = n.AreaID; var nodeid = n.NodeID; if (copy == null) { copy = CurrentPathNode; } if (copy != null) { n.Init(CurrentYndFile, copy.RawData); n.LinkCountUnk = copy.LinkCountUnk; } n.AreaID = areaid; n.NodeID = nodeid; bool cp = copyPosition && (copy != null); Vector3 pos = cp ? copy.Position : GetSpawnPos(10.0f); n.SetPosition(pos); if (copy != null) { var link1 = n.AddLink(copy); var link2 = copy.AddLink(n); if ((copy.Links != null) && (copy.Links.Length > 0)) { var clink = copy.Links[0]; link1.CopyFlags(clink); var clnode = clink.Node2; if (clnode.Links != null) { for (int i = 0; i < clnode.Links.Length; i++) { var clnlink = clnode.Links[i]; if (clnlink.Node2 == copy) { link2.CopyFlags(clnlink); break; } } } } } CurrentYndFile.UpdateAllNodePositions(); //for the graphics... CurrentYndFile.BuildBVH(); LoadProjectTree(); TrySelectPathNodeTreeNode(n); CurrentPathNode = n; LoadYndTabPage(); LoadPathNodeTabPage(); if (WorldForm != null) { WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); } } public bool DeletePathNode() { if (CurrentYndFile == null) return false; if (CurrentPathNode == null) return false; if (CurrentPathNode.Ynd != CurrentYndFile) return false; if (CurrentYndFile.Nodes == null) return false; //nothing to delete.. if (MessageBox.Show("Are you sure you want to delete this path node?\n" + CurrentPathNode.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return true; } //find this now to remove it later. var tn = FindPathNodeTreeNode(CurrentPathNode); bool res = false; if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { res = CurrentYndFile.RemoveNode(CurrentPathNode); //WorldForm.SelectItem(null, null, null); } } else { res = CurrentYndFile.RemoveNode(CurrentPathNode); } if (!res) { MessageBox.Show("Unable to delete the path node. This shouldn't happen!"); } SetYndHasChangedUI(true); CurrentPathNode = null; if ((tn != null) && (tn.Parent != null)) { tn.Parent.Text = "Nodes (" + CurrentYndFile.Nodes.Length.ToString() + ")"; tn.Parent.Nodes.Remove(tn); } else { //no need for this when removing the node above will select something else. LoadPathNodeTabPage(); //this case really shouldn't happen... } if (WorldForm != null) { WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); } return true; } private void AddPathNodeToProject() { if (CurrentPathNode == null) return; if (CurrentYndFile != null) { AddYndToProject(CurrentYndFile); } } private void LoadPathNodeTabPage() { CurrentPathLink = null; if (CurrentPathNode == null) { YndNodePanel.Enabled = false; PathNodeDeleteButton.Enabled = false; PathNodeAddToProjectButton.Enabled = false; PathNodeAreaIDUpDown.Value = 0; PathNodeNodeIDUpDown.Value = 0; PathNodePositionTextBox.Text = string.Empty; PathNodeStreetHashTextBox.Text = string.Empty; PathNodeStreetNameLabel.Text = "Name: [None]"; UpdatePathNodeFlagsUI(true, true); PathNodeLinkCountLabel.Text = "Link Count: 0"; PathNodeLinksListBox.Items.Clear(); } else { populatingui = true; var n = CurrentPathNode.RawData; YndNodePanel.Enabled = true; PathNodeDeleteButton.Enabled = YndExistsInProject(CurrentYndFile); PathNodeAddToProjectButton.Enabled = !PathNodeDeleteButton.Enabled; var streetname = GlobalText.TryGetString(n.StreetName.Hash); PathNodeAreaIDUpDown.Value = n.AreaID; PathNodeNodeIDUpDown.Value = n.NodeID; PathNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentPathNode.Position); PathNodeStreetHashTextBox.Text = n.StreetName.Hash.ToString(); PathNodeStreetNameLabel.Text = "Name: " + ((n.StreetName.Hash == 0) ? "[None]" : (string.IsNullOrEmpty(streetname) ? "[Not found]" : streetname)); UpdatePathNodeFlagsUI(true, true); PathNodeLinkCountLabel.Text = "Link Count: " + CurrentPathNode.LinkCount.ToString(); PathNodeLinksListBox.Items.Clear(); if (CurrentPathNode.Links != null) { foreach (var link in CurrentPathNode.Links) { PathNodeLinksListBox.Items.Add(link); } } populatingui = false; if (WorldForm != null) { WorldForm.SelectPathNode(CurrentPathNode); } } LoadPathNodeJunctionPage(); LoadPathNodeLinkPage(); } private void LoadPathNodeLinkPage() { if (CurrentPathLink == null) { PathNodeLinkPanel.Enabled = false; PathNodeLinkAreaIDUpDown.Value = 0; PathNodeLinkNodeIDUpDown.Value = 0; UpdatePathNodeLinkFlagsUI(true, true); PathNodeLinkLengthUpDown.Value = 0; PathNodeLinkageStatusLabel.Text = ""; } else { populatingui = true; PathNodeLinkPanel.Enabled = true; PathNodeLinkAreaIDUpDown.Value = CurrentPathLink._RawData.AreaID; PathNodeLinkNodeIDUpDown.Value = CurrentPathLink._RawData.NodeID; UpdatePathNodeLinkFlagsUI(true, true); PathNodeLinkLengthUpDown.Value = CurrentPathLink.LinkLength.Value; PathNodeLinkageStatusLabel.Text = ""; populatingui = false; if (WorldForm != null) { WorldForm.SelectPathLink(CurrentPathLink); } } } private void LoadPathNodeJunctionPage() { var junc = CurrentPathNode?.Junction; if (junc == null) { PathNodeJunctionEnableCheckBox.Checked = false; PathNodeJunctionPanel.Enabled = false; PathNodeJunctionMaxZUpDown.Value = 0; PathNodeJunctionMinZUpDown.Value = 0; PathNodeJunctionPosXUpDown.Value = 0; PathNodeJunctionPosYUpDown.Value = 0; PathNodeJunctionHeightmapDimXUpDown.Value = 1; PathNodeJunctionHeightmapDimYUpDown.Value = 1; PathNodeJunctionHeightmapBytesTextBox.Text = string.Empty; } else { populatingui = true; PathNodeJunctionEnableCheckBox.Checked = CurrentPathNode.HasJunction; PathNodeJunctionPanel.Enabled = PathNodeJunctionEnableCheckBox.Checked; PathNodeJunctionMaxZUpDown.Value = junc.MaxZ; PathNodeJunctionMinZUpDown.Value = junc.MinZ; PathNodeJunctionPosXUpDown.Value = junc.PositionX; PathNodeJunctionPosYUpDown.Value = junc.PositionY; PathNodeJunctionHeightmapDimXUpDown.Value = junc.Heightmap.CountX; PathNodeJunctionHeightmapDimYUpDown.Value = junc.Heightmap.CountY; PathNodeJunctionHeightmapBytesTextBox.Text = junc.Heightmap?.GetDataString() ?? ""; populatingui = false; } } public bool IsCurrentPathNode(YndNode pathnode) { return CurrentPathNode == pathnode; } private void UpdatePathNodeFlagsUI(bool updateCheckboxes, bool updateUpDowns) { var flags0 = CurrentPathNode?.Flags0.Value ?? 0; var flags1 = CurrentPathNode?.Flags1.Value ?? 0; var flags2 = CurrentPathNode?.Flags2.Value ?? 0; var flags3 = CurrentPathNode?.Flags3.Value ?? 0; var flags4 = CurrentPathNode?.Flags4.Value ?? 0; var flags5 = (uint)(CurrentPathNode?.LinkCountUnk ?? 0); if (updateCheckboxes) { PathNodeFlags01CheckBox.Checked = IsBitSet(flags0, 0); PathNodeFlags02CheckBox.Checked = IsBitSet(flags0, 1); PathNodeFlags03CheckBox.Checked = IsBitSet(flags0, 2); PathNodeFlags04CheckBox.Checked = IsBitSet(flags0, 3); PathNodeFlags05CheckBox.Checked = IsBitSet(flags0, 4); PathNodeFlags06CheckBox.Checked = IsBitSet(flags0, 5); PathNodeFlags07CheckBox.Checked = IsBitSet(flags0, 6); PathNodeFlags08CheckBox.Checked = IsBitSet(flags0, 7); PathNodeFlags11CheckBox.Checked = IsBitSet(flags1, 0); PathNodeFlags12CheckBox.Checked = IsBitSet(flags1, 1); PathNodeFlags13CheckBox.Checked = IsBitSet(flags1, 2); PathNodeFlags14CheckBox.Checked = IsBitSet(flags1, 3); PathNodeFlags15CheckBox.Checked = IsBitSet(flags1, 4); PathNodeFlags16CheckBox.Checked = IsBitSet(flags1, 5); PathNodeFlags17CheckBox.Checked = IsBitSet(flags1, 6); PathNodeFlags18CheckBox.Checked = IsBitSet(flags1, 7); PathNodeFlags21CheckBox.Checked = IsBitSet(flags2, 0); PathNodeFlags22CheckBox.Checked = IsBitSet(flags2, 1); PathNodeFlags23CheckBox.Checked = IsBitSet(flags2, 2); PathNodeFlags24CheckBox.Checked = IsBitSet(flags2, 3); PathNodeFlags25CheckBox.Checked = IsBitSet(flags2, 4); PathNodeFlags26CheckBox.Checked = IsBitSet(flags2, 5); PathNodeFlags27CheckBox.Checked = IsBitSet(flags2, 6); PathNodeFlags28CheckBox.Checked = IsBitSet(flags2, 7); PathNodeFlags31CheckBox.Checked = IsBitSet(flags3, 0); PathNodeFlags32UpDown.Value = (flags3 >> 1) & 127; PathNodeFlags41CheckBox.Checked = IsBitSet(flags4, 0); PathNodeFlags42UpDown.Value = (flags4 >> 1) & 7; PathNodeFlags45CheckBox.Checked = IsBitSet(flags4, 4); PathNodeFlags46CheckBox.Checked = IsBitSet(flags4, 5); PathNodeFlags47CheckBox.Checked = IsBitSet(flags4, 6); PathNodeFlags48CheckBox.Checked = IsBitSet(flags4, 7); PathNodeFlags51CheckBox.Checked = IsBitSet(flags5, 0); PathNodeFlags52CheckBox.Checked = IsBitSet(flags5, 1); PathNodeFlags53CheckBox.Checked = IsBitSet(flags5, 2); } if (updateUpDowns) { PathNodeFlags0UpDown.Value = flags0; PathNodeFlags1UpDown.Value = flags1; PathNodeFlags2UpDown.Value = flags2; PathNodeFlags3UpDown.Value = flags3; PathNodeFlags4UpDown.Value = flags4; PathNodeFlags5UpDown.Value = flags5; } var n = CurrentPathNode; if (n != null) { PathNodeFlags0Label.Text = n.Flags0.ToHexString(); PathNodeFlags1Label.Text = n.Flags1.ToHexString(); PathNodeFlags2Label.Text = n.Flags2.ToHexString(); PathNodeFlags3Label.Text = n.Flags3.ToHexString(); PathNodeFlags4Label.Text = n.Flags4.ToHexString(); } else { PathNodeFlags0Label.Text = "0x00"; PathNodeFlags1Label.Text = "0x00"; PathNodeFlags2Label.Text = "0x00"; PathNodeFlags3Label.Text = "0x00"; PathNodeFlags4Label.Text = "0x00"; } } private void SetPathNodeFlagsFromCheckBoxes() { if (populatingui) return; if (CurrentPathNode == null) return; uint flags0 = 0; uint flags1 = 0; uint flags2 = 0; uint flags3 = 0; uint flags4 = 0; uint flags5 = 0; flags0 = UpdateBit(flags0, 0, PathNodeFlags01CheckBox.Checked); flags0 = UpdateBit(flags0, 1, PathNodeFlags02CheckBox.Checked); flags0 = UpdateBit(flags0, 2, PathNodeFlags03CheckBox.Checked); flags0 = UpdateBit(flags0, 3, PathNodeFlags04CheckBox.Checked); flags0 = UpdateBit(flags0, 4, PathNodeFlags05CheckBox.Checked); flags0 = UpdateBit(flags0, 5, PathNodeFlags06CheckBox.Checked); flags0 = UpdateBit(flags0, 6, PathNodeFlags07CheckBox.Checked); flags0 = UpdateBit(flags0, 7, PathNodeFlags08CheckBox.Checked); flags1 = UpdateBit(flags1, 0, PathNodeFlags11CheckBox.Checked); flags1 = UpdateBit(flags1, 1, PathNodeFlags12CheckBox.Checked); flags1 = UpdateBit(flags1, 2, PathNodeFlags13CheckBox.Checked); flags1 = UpdateBit(flags1, 3, PathNodeFlags14CheckBox.Checked); flags1 = UpdateBit(flags1, 4, PathNodeFlags15CheckBox.Checked); flags1 = UpdateBit(flags1, 5, PathNodeFlags16CheckBox.Checked); flags1 = UpdateBit(flags1, 6, PathNodeFlags17CheckBox.Checked); flags1 = UpdateBit(flags1, 7, PathNodeFlags18CheckBox.Checked); flags2 = UpdateBit(flags2, 0, PathNodeFlags21CheckBox.Checked); flags2 = UpdateBit(flags2, 1, PathNodeFlags22CheckBox.Checked); flags2 = UpdateBit(flags2, 2, PathNodeFlags23CheckBox.Checked); flags2 = UpdateBit(flags2, 3, PathNodeFlags24CheckBox.Checked); flags2 = UpdateBit(flags2, 4, PathNodeFlags25CheckBox.Checked); flags2 = UpdateBit(flags2, 5, PathNodeFlags26CheckBox.Checked); flags2 = UpdateBit(flags2, 6, PathNodeFlags27CheckBox.Checked); flags2 = UpdateBit(flags2, 7, PathNodeFlags28CheckBox.Checked); flags3 = UpdateBit(flags3, 0, PathNodeFlags31CheckBox.Checked); flags3 += (((uint)PathNodeFlags32UpDown.Value & 127u) << 1); flags4 = UpdateBit(flags4, 0, PathNodeFlags41CheckBox.Checked); flags4 += (((uint)PathNodeFlags42UpDown.Value & 7u) << 1); flags4 = UpdateBit(flags4, 4, PathNodeFlags45CheckBox.Checked); flags4 = UpdateBit(flags4, 5, PathNodeFlags46CheckBox.Checked); flags4 = UpdateBit(flags4, 6, PathNodeFlags47CheckBox.Checked); flags4 = UpdateBit(flags4, 7, PathNodeFlags48CheckBox.Checked); flags5 = UpdateBit(flags5, 0, PathNodeFlags51CheckBox.Checked); flags5 = UpdateBit(flags5, 1, PathNodeFlags52CheckBox.Checked); flags5 = UpdateBit(flags5, 2, PathNodeFlags53CheckBox.Checked); lock (yndsyncroot) { if (CurrentPathNode.Flags0.Value != flags0) { CurrentPathNode.Flags0 = (byte)flags0; SetYndHasChanged(true); } if (CurrentPathNode.Flags1.Value != flags1) { CurrentPathNode.Flags1 = (byte)flags1; SetYndHasChanged(true); } if (CurrentPathNode.Flags2.Value != flags2) { CurrentPathNode.Flags2 = (byte)flags2; SetYndHasChanged(true); } if (CurrentPathNode.Flags3.Value != flags3) { CurrentPathNode.Flags3 = (byte)flags3; SetYndHasChanged(true); } if (CurrentPathNode.Flags4.Value != flags4) { CurrentPathNode.Flags4 = (byte)flags4; SetYndHasChanged(true); } if (CurrentPathNode.LinkCountUnk != flags5) { CurrentPathNode.LinkCountUnk = (byte)flags5; SetYndHasChanged(true); } } populatingui = true; UpdatePathNodeFlagsUI(false, true); //update updowns populatingui = false; } private void SetPathNodeFlagsFromUpDowns() { if (populatingui) return; if (CurrentPathNode == null) return; uint flags0 = (uint)PathNodeFlags0UpDown.Value; uint flags1 = (uint)PathNodeFlags1UpDown.Value; uint flags2 = (uint)PathNodeFlags2UpDown.Value; uint flags3 = (uint)PathNodeFlags3UpDown.Value; uint flags4 = (uint)PathNodeFlags4UpDown.Value; uint flags5 = (uint)PathNodeFlags5UpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Flags0.Value != flags0) { CurrentPathNode.Flags0 = (byte)flags0; SetYndHasChanged(true); } if (CurrentPathNode.Flags1.Value != flags1) { CurrentPathNode.Flags1 = (byte)flags1; SetYndHasChanged(true); } if (CurrentPathNode.Flags2.Value != flags2) { CurrentPathNode.Flags2 = (byte)flags2; SetYndHasChanged(true); } if (CurrentPathNode.Flags3.Value != flags3) { CurrentPathNode.Flags3 = (byte)flags3; SetYndHasChanged(true); } if (CurrentPathNode.Flags4.Value != flags4) { CurrentPathNode.Flags4 = (byte)flags4; SetYndHasChanged(true); } if (CurrentPathNode.LinkCountUnk != flags5) { CurrentPathNode.LinkCountUnk = (byte)flags5; SetYndHasChanged(true); } } populatingui = true; UpdatePathNodeFlagsUI(true, false); //update checkboxes populatingui = false; } private void UpdatePathNodeLinkFlagsUI(bool updateCheckboxes, bool updateUpDowns) { var flags0 = CurrentPathLink?.Flags0.Value ?? 0; var flags1 = CurrentPathLink?.Flags1.Value ?? 0; var flags2 = CurrentPathLink?.Flags2.Value ?? 0; if (updateCheckboxes) { PathNodeLinkFlags01CheckBox.Checked = IsBitSet(flags0, 0); PathNodeLinkFlags02CheckBox.Checked = IsBitSet(flags0, 1); PathNodeLinkFlags03UpDown.Value = (flags0 >> 2) & 7; PathNodeLinkFlags04UpDown.Value = (flags0 >> 5) & 7; PathNodeLinkFlags11CheckBox.Checked = IsBitSet(flags1, 0); PathNodeLinkFlags12CheckBox.Checked = IsBitSet(flags1, 1); PathNodeLinkFlags13CheckBox.Checked = IsBitSet(flags1, 2); PathNodeLinkFlags14CheckBox.Checked = IsBitSet(flags1, 3); PathNodeLinkOffsetSizeUpDown.Value = (flags1 >> 4) & 7; PathNodeLinkFlags18CheckBox.Checked = IsBitSet(flags1, 7); PathNodeLinkFlags21CheckBox.Checked = IsBitSet(flags2, 0); PathNodeLinkFlags22CheckBox.Checked = IsBitSet(flags2, 1); PathNodeLinkBackLanesUpDown.Value = (flags2 >> 2) & 7; PathNodeLinkFwdLanesUpDown.Value = (flags2 >> 5) & 7; } if (updateUpDowns) { PathNodeLinkFlags0UpDown.Value = flags0; PathNodeLinkFlags1UpDown.Value = flags1; PathNodeLinkFlags2UpDown.Value = flags2; } var l = CurrentPathLink; if (l != null) { PathNodeLinkFlags0Label.Text = l.Flags0.ToHexString(); PathNodeLinkFlags1Label.Text = l.Flags1.ToHexString(); PathNodeLinkFlags2Label.Text = l.Flags2.ToHexString(); } else { PathNodeLinkFlags0Label.Text = "0x00"; PathNodeLinkFlags1Label.Text = "0x00"; PathNodeLinkFlags2Label.Text = "0x00"; } } private void SetPathNodeLinkFlagsFromCheckBoxes() { if (populatingui) return; if (CurrentPathLink == null) return; uint flags0 = 0; uint flags1 = 0; uint flags2 = 0; flags0 = UpdateBit(flags0, 0, PathNodeLinkFlags01CheckBox.Checked); flags0 = UpdateBit(flags0, 1, PathNodeLinkFlags02CheckBox.Checked); flags0 += (((uint)PathNodeLinkFlags03UpDown.Value & 7u) << 2); flags0 += (((uint)PathNodeLinkFlags04UpDown.Value & 7u) << 5); flags1 = UpdateBit(flags1, 0, PathNodeLinkFlags11CheckBox.Checked); flags1 = UpdateBit(flags1, 1, PathNodeLinkFlags12CheckBox.Checked); flags1 = UpdateBit(flags1, 2, PathNodeLinkFlags13CheckBox.Checked); flags1 = UpdateBit(flags1, 3, PathNodeLinkFlags14CheckBox.Checked); flags1 += (((uint)PathNodeLinkOffsetSizeUpDown.Value & 7u) << 4); flags1 = UpdateBit(flags1, 7, PathNodeLinkFlags18CheckBox.Checked); flags2 = UpdateBit(flags2, 0, PathNodeLinkFlags21CheckBox.Checked); flags2 = UpdateBit(flags2, 1, PathNodeLinkFlags22CheckBox.Checked); flags2 += (((uint)PathNodeLinkBackLanesUpDown.Value & 7u) << 2); flags2 += (((uint)PathNodeLinkFwdLanesUpDown.Value & 7u) << 5); bool updgfx = false; lock (yndsyncroot) { if (CurrentPathLink.Flags0.Value != flags0) { CurrentPathLink.Flags0 = (byte)flags0; SetYndHasChanged(true); } if (CurrentPathLink.Flags1.Value != flags1) { CurrentPathLink.Flags1 = (byte)flags1; SetYndHasChanged(true); updgfx = true; } if (CurrentPathLink.Flags2.Value != flags2) { CurrentPathLink.Flags2 = (byte)flags2; SetYndHasChanged(true); updgfx = true; } } populatingui = true; UpdatePathNodeLinkFlagsUI(false, true); //update updowns populatingui = false; if (updgfx && (WorldForm != null) && (CurrentYndFile != null)) { WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); } } private void SetPathNodeLinkFlagsFromUpDowns() { if (populatingui) return; if (CurrentPathLink == null) return; uint flags0 = (uint)PathNodeLinkFlags0UpDown.Value; uint flags1 = (uint)PathNodeLinkFlags1UpDown.Value; uint flags2 = (uint)PathNodeLinkFlags2UpDown.Value; bool updgfx = false; lock (yndsyncroot) { if (CurrentPathLink.Flags0.Value != flags0) { CurrentPathLink.Flags0 = (byte)flags0; SetYndHasChanged(true); } if (CurrentPathLink.Flags1.Value != flags1) { CurrentPathLink.Flags1 = (byte)flags1; SetYndHasChanged(true); } if (CurrentPathLink.Flags2.Value != flags2) { CurrentPathLink.Flags2 = (byte)flags2; SetYndHasChanged(true); updgfx = true; } } populatingui = true; UpdatePathNodeLinkFlagsUI(true, false); //update checkboxes populatingui = false; if (updgfx && (WorldForm != null) && (CurrentYndFile != null)) { WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); } } private void AddPathLink() { if (CurrentPathNode == null) return; var l = CurrentPathNode.AddLink(); LoadPathNodeTabPage(); PathNodeLinksListBox.SelectedItem = l; if (WorldForm != null) { WorldForm.UpdatePathNodeGraphics(CurrentPathNode, false); } } private void RemovePathLink() { if (CurrentPathLink == null) return; if (CurrentPathNode == null) return; var r = CurrentPathNode.RemoveLink(CurrentPathLink); if (!r) return; LoadPathNodeTabPage(); if (WorldForm != null) { WorldForm.UpdatePathNodeGraphics(CurrentPathNode, false); } } private void UpdatePathNodeLinkage() { if (CurrentPathLink == null) return; if (CurrentYndFile == null) return; YndNode linknode = null; ushort areaid = CurrentPathLink._RawData.AreaID; ushort nodeid = CurrentPathLink._RawData.NodeID; if (areaid == CurrentYndFile.AreaID) { //link to the same ynd. find the new node in the current ynd. if ((CurrentYndFile.Nodes != null) && (nodeid < CurrentYndFile.Nodes.Length)) { linknode = CurrentYndFile.Nodes[nodeid]; } } else { //try lookup the link node from the space. if (WorldForm != null) { linknode = WorldForm.GetPathNodeFromSpace(areaid, nodeid); } } if (linknode == null) { PathNodeLinkageStatusLabel.Text = "Unable to find node " + areaid.ToString() + ":" + nodeid.ToString() + "."; } else { PathNodeLinkageStatusLabel.Text = ""; } CurrentPathLink.Node2 = linknode; CurrentPathLink.UpdateLength(); ////need to rebuild the link verts.. updating the graphics should do it... if (WorldForm != null) { WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); } } public void NewYnv()//TODO! { } public void OpenYnv()//TODO! { } public void SaveYnv(bool saveas = false)//TODO! { } private void AddYnvToProject(YnvFile ynv)//TODO! { } private void RemoveYnvFromProject()//TODO! { } private void LoadYnvTabPage()//TODO! { } private void LoadYnvFromFile(YnvFile ynv, string filename)//TODO! { } private void LoadYnvTreeNodes(YnvFile ynv, TreeNode node)//TODO! { } private void SetYnvHasChanged(bool changed)//TODO! { } private void SetYnvHasChangedUI(bool changed)//TODO! { } public void NewNavPoly(YnvPoly copy = null, bool copyposition = false)//TODO! { } public bool DeleteNavPoly()//TODO! { return false; } private void AddNavPolyToProject()//TODO! { } private void LoadNavPolyTabPage()//TODO! { } public bool IsCurrentNavPoly(YnvPoly poly) { return poly == CurrentNavPoly; } public void NewTrainTrack() { if (CurrentProjectFile == null) { NewProject(); } if (CurrentProjectFile == null) return; int testi = 13; string fname = string.Empty; bool filenameok = false; while (!filenameok) { fname = "trains" + testi.ToString() + ".dat"; filenameok = !CurrentProjectFile.ContainsTrainTrack(fname); testi++; } lock (trainsyncroot) { TrainTrack track = CurrentProjectFile.AddTrainsFile(fname); if (track != null) { track.Loaded = true; track.HasChanged = true; //new track, flag as not saved //TODO: set new train track default values... } } CurrentProjectFile.HasChanged = true; LoadProjectTree(); } public void OpenTrainTrack() { string[] files = ShowOpenDialogMulti("Dat files|*.dat", string.Empty); if (files == null) { return; } if (CurrentProjectFile == null) { NewProject(); } foreach (string file in files) { if (!File.Exists(file)) continue; var track = CurrentProjectFile.AddTrainsFile(file); if (track != null) { SetProjectHasChanged(true); LoadTrainTrackFromFile(track, file); LoadProjectTree(); } else { MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); } } } public void SaveTrainTrack(bool saveas = false) { if ((CurrentTrainTrack == null) && (CurrentTrainNode != null)) CurrentTrainTrack = CurrentTrainNode.Track; if (CurrentTrainTrack == null) return; string trackname = CurrentTrainTrack.Name; string filepath = CurrentTrainTrack.FilePath; if (string.IsNullOrEmpty(filepath)) { filepath = trackname; } string origfile = filepath; if (!File.Exists(filepath)) { saveas = true; } byte[] data; lock (trainsyncroot) //need to sync writes to ynd objects... { saveas = saveas || string.IsNullOrEmpty(filepath); if (saveas) { filepath = ShowSaveDialog("Dat files|*.dat", filepath); if (string.IsNullOrEmpty(filepath)) { return; } string newname = Path.GetFileNameWithoutExtension(filepath); //JenkIndex.Ensure(newname); CurrentTrainTrack.FilePath = filepath; CurrentTrainTrack.RpfFileEntry.Name = new FileInfo(filepath).Name; CurrentTrainTrack.Name = CurrentTrainTrack.RpfFileEntry.Name; } data = CurrentTrainTrack.Save(); } if (data != null) { File.WriteAllBytes(filepath, data); } SetTrainTrackHasChanged(false); if (saveas) { LoadTrainTrackTabPage(); if (CurrentProjectFile != null) { string origpath = CurrentProjectFile.GetRelativePath(origfile); string newpath = CurrentProjectFile.GetRelativePath(CurrentTrainTrack.FilePath); if (!CurrentProjectFile.RenameTrainTrack(origpath, newpath)) { //couldn't rename it in the project? happens when project not saved yet... //MessageBox.Show("Couldn't rename train track in project! This shouldn't happen - check the project file XML."); } } SetProjectHasChanged(true); SetCurrentSaveItem(); } } private void AddTrainTrackToProject(TrainTrack track) { if (track == null) return; if (CurrentProjectFile == null) { NewProject(); } if (TrainTrackExistsInProject(track)) return; if (CurrentProjectFile.AddTrainsFile(track)) { track.HasChanged = true; CurrentProjectFile.HasChanged = true; LoadProjectTree(); } CurrentTrainTrack = track; RefreshUI(); if (CurrentTrainNode != null) { TrySelectTrainNodeTreeNode(CurrentTrainNode); } } private void RemoveTrainTrackFromProject() { if (CurrentTrainTrack == null) return; if (CurrentProjectFile == null) return; CurrentProjectFile.RemoveTrainsFile(CurrentTrainTrack); CurrentTrainTrack = null; LoadProjectTree(); RefreshUI(); } private void LoadTrainTrackTabPage() { if (CurrentTrainTrack == null) { TrainTrackFilePanel.Enabled = false; TrainTrackFilenameTextBox.Text = string.Empty; TrainTrackConfigNameTextBox.Text = string.Empty; TrainTrackIsPingPongCheckBox.Checked = false; TrainTrackStopsAtStationsCheckBox.Checked = false; TrainTrackMPStopsAtStationsCheckBox.Checked = false; TrainTrackSpeedTextBox.Text = string.Empty; TrainTrackBrakingDistTextBox.Text = string.Empty; TrainTrackRpfPathTextBox.Text = string.Empty; TrainTrackFilePathTextBox.Text = string.Empty; TrainTrackProjectPathTextBox.Text = string.Empty; TrainTrackInfoLabel.Text = string.Empty; } else { populatingui = true; TrainTrackFilePanel.Enabled = true; TrainTrackFilenameTextBox.Text = CurrentTrainTrack.filename; TrainTrackConfigNameTextBox.Text = CurrentTrainTrack.trainConfigName; TrainTrackIsPingPongCheckBox.Checked = CurrentTrainTrack.isPingPongTrack; TrainTrackStopsAtStationsCheckBox.Checked = CurrentTrainTrack.stopsAtStations; TrainTrackMPStopsAtStationsCheckBox.Checked = CurrentTrainTrack.MPstopsAtStations; TrainTrackSpeedTextBox.Text = FloatUtil.ToString(CurrentTrainTrack.speed); TrainTrackBrakingDistTextBox.Text = FloatUtil.ToString(CurrentTrainTrack.brakingDist); TrainTrackRpfPathTextBox.Text = CurrentTrainTrack.RpfFileEntry?.Path ?? string.Empty; TrainTrackFilePathTextBox.Text = string.Empty; //todo TrainTrackProjectPathTextBox.Text = string.Empty; //todo TrainTrackInfoLabel.Text = CurrentTrainTrack.StationCount.ToString() + " stations"; populatingui = false; } } private void LoadTrainTrackFromFile(TrainTrack track, string filename) { byte[] data = File.ReadAllBytes(filename); string fname = new FileInfo(filename).Name; track.Load(data); track.Name = fname; track.FilePath = filename; track.RpfFileEntry.Name = fname; track.RpfFileEntry.NameLower = fname.ToLowerInvariant(); if (WorldForm != null) { WorldForm.UpdateTrainTrackGraphics(track, true); //links don't get drawn until something changes otherwise } } private void LoadTrainTrackTreeNodes(TrainTrack track, TreeNode node) { if (track == null) return; if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Nodes node.Nodes.Clear(); if ((track.Nodes != null) && (track.Nodes.Count > 0)) { var nodesnode = node.Nodes.Add("Nodes (" + track.Nodes.Count.ToString() + ")"); nodesnode.Name = "Nodes"; nodesnode.Tag = track; var nodes = track.Nodes; for (int i = 0; i < nodes.Count; i++) { var ynode = nodes[i]; var tnode = nodesnode.Nodes.Add(ynode.ToString()); tnode.Tag = ynode; } } } private void SetTrainTrackHasChanged(bool changed) { if (CurrentTrainTrack == null) return; bool changechange = changed != CurrentTrainTrack.HasChanged; if (!changechange) return; CurrentTrainTrack.HasChanged = changed; SetTrainTrackHasChangedUI(changed); } private void SetTrainTrackHasChangedUI(bool changed) { if (ProjectTreeView.Nodes.Count > 0) { var pnode = ProjectTreeView.Nodes[0]; var trnode = GetChildTreeNode(pnode, "Trains"); if (trnode == null) return; string changestr = changed ? "*" : ""; for (int i = 0; i < trnode.Nodes.Count; i++) { var tnode = trnode.Nodes[i]; if (tnode.Tag == CurrentTrainTrack) { string name = CurrentTrainTrack.Name; if (CurrentTrainTrack.RpfFileEntry != null) { name = CurrentTrainTrack.RpfFileEntry.Name; } tnode.Text = changestr + name; break; } } } } public void NewTrainNode(TrainTrackNode copy = null, bool copyPosition = false) { if (CurrentTrainTrack == null) return; var afternode = copyPosition ? copy : null; var n = CurrentTrainTrack.AddNode(afternode); if (copy == null) { copy = CurrentTrainNode; } if (copy != null) { n.NodeType = copy.NodeType; } bool cp = copyPosition && (copy != null); Vector3 pos = cp ? copy.Position : GetSpawnPos(10.0f); n.SetPosition(pos); //CurrentTrainTrack.BuildVertices(); //for the graphics... CurrentTrainTrack.BuildBVH(); LoadProjectTree(); TrySelectTrainNodeTreeNode(n); CurrentTrainNode = n; LoadTrainNodeTabPage(); if (WorldForm != null) { WorldForm.UpdateTrainTrackGraphics(CurrentTrainTrack, false); } } public bool DeleteTrainNode() { if (CurrentTrainTrack == null) return false; if (CurrentTrainNode == null) return false; if (CurrentTrainNode.Track != CurrentTrainTrack) return false; if (CurrentTrainTrack.Nodes == null) return false; //nothing to delete.. if (MessageBox.Show("Are you sure you want to delete this train track node?\n" + CurrentTrainNode.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return true; } //find this now to remove it later. var tn = FindTrainNodeTreeNode(CurrentTrainNode); bool res = false; if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { res = CurrentTrainTrack.RemoveNode(CurrentTrainNode); //WorldForm.SelectItem(null, null, null); } } else { res = CurrentTrainTrack.RemoveNode(CurrentTrainNode); } if (!res) { MessageBox.Show("Unable to delete the train track node. This shouldn't happen!"); } SetTrainTrackHasChangedUI(true); CurrentTrainNode = null; if ((tn != null) && (tn.Parent != null)) { tn.Parent.Text = "Nodes (" + CurrentTrainTrack.Nodes.Count.ToString() + ")"; tn.Parent.Nodes.Remove(tn); } else { //no need for this when removing the node above will select something else. LoadTrainNodeTabPage(); //this case really shouldn't happen... } if (WorldForm != null) { WorldForm.UpdateTrainTrackGraphics(CurrentTrainTrack, false); } return true; } private void AddTrainNodeToProject() { if (CurrentTrainNode == null) return; if (CurrentTrainTrack != null) { AddTrainTrackToProject(CurrentTrainTrack); } } private void LoadTrainNodeTabPage() { if (CurrentTrainNode == null) { TrainNodePanel.Enabled = false; TrainNodeDeleteButton.Enabled = false; TrainNodeAddToProjectButton.Enabled = false; TrainNodePositionTextBox.Text = string.Empty; TrainNodeTypeComboBox.SelectedIndex = -1; } else { populatingui = true; TrainNodePanel.Enabled = true; TrainNodeDeleteButton.Enabled = TrainTrackExistsInProject(CurrentTrainTrack); TrainNodeAddToProjectButton.Enabled = !TrainNodeDeleteButton.Enabled; TrainNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentTrainNode.Position); TrainNodeTypeComboBox.SelectedIndex = CurrentTrainNode.NodeType; populatingui = false; if (WorldForm != null) { WorldForm.SelectTrainTrackNode(CurrentTrainNode); } } } public bool IsCurrentTrainNode(TrainTrackNode node) { return node == CurrentTrainNode; } public void NewScenario() { if (CurrentProjectFile == null) { NewProject(); } if (CurrentProjectFile == null) return; int testi = 1; string fname = string.Empty; bool filenameok = false; while (!filenameok) { fname = "scenario" + testi.ToString() + ".ymt"; filenameok = !CurrentProjectFile.ContainsScenario(fname); testi++; } lock (scenariosyncroot) { YmtFile ymt = CurrentProjectFile.AddScenarioFile(fname); if (ymt != null) { ymt.CScenarioPointRegion = new MCScenarioPointRegion(); ymt.CScenarioPointRegion.Ymt = ymt; ymt.CScenarioPointRegion.Points = new MCScenarioPointContainer(ymt.CScenarioPointRegion); ymt.CScenarioPointRegion.Paths = new MUnk_4023740759(ymt.CScenarioPointRegion); ymt.CScenarioPointRegion.LookUps = new MCScenarioPointLookUps(ymt.CScenarioPointRegion); ymt.ScenarioRegion = new ScenarioRegion(); ymt.ScenarioRegion.Region = ymt.CScenarioPointRegion; ymt.ScenarioRegion.Ymt = ymt; ymt.ScenarioRegion.BuildNodes(); //should be empty ymt.ScenarioRegion.BuildBVH(); //should be empty ymt.ScenarioRegion.BuildVertices(); //should be empty ymt.HasChanged = true; //new ymt, flag as not saved ymt.Loaded = true; } } CurrentProjectFile.HasChanged = true; LoadProjectTree(); } public void OpenScenario() { string[] files = ShowOpenDialogMulti("Ymt files|*.ymt", string.Empty); if (files == null) { return; } if (CurrentProjectFile == null) { NewProject(); } foreach (string file in files) { if (!File.Exists(file)) continue; var ymt = CurrentProjectFile.AddScenarioFile(file); if (ymt != null) { SetProjectHasChanged(true); LoadScenarioFromFile(ymt, file); LoadProjectTree(); } else { MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); } } } public void SaveScenario(bool saveas = false) { if ((CurrentScenario == null) && (CurrentScenarioNode != null)) CurrentScenario = CurrentScenarioNode.Ymt; if (CurrentScenario == null) return; string ymtname = CurrentScenario.Name; string filepath = CurrentScenario.FilePath; if (string.IsNullOrEmpty(filepath)) { filepath = ymtname; } string origfile = filepath; if (!File.Exists(filepath)) { saveas = true; } byte[] data; lock (scenariosyncroot) //need to sync writes to scenario... { saveas = saveas || string.IsNullOrEmpty(filepath); if (saveas) { filepath = ShowSaveDialog("Ymt files|*.ymt", filepath); if (string.IsNullOrEmpty(filepath)) { return; } string newname = Path.GetFileNameWithoutExtension(filepath); JenkIndex.Ensure(newname); CurrentScenario.FilePath = filepath; CurrentScenario.RpfFileEntry.Name = new FileInfo(filepath).Name; CurrentScenario.Name = CurrentScenario.RpfFileEntry.Name; } CurrentScenario.ContentType = YmtFileContentType.ScenarioPointRegion;//just to be sure.. data = CurrentScenario.Save(); } if (data != null) { File.WriteAllBytes(filepath, data); } SetScenarioHasChanged(false); if (saveas) { LoadScenarioTabPage(); if (CurrentProjectFile != null) { string origpath = CurrentProjectFile.GetRelativePath(origfile); string newpath = CurrentProjectFile.GetRelativePath(CurrentScenario.FilePath); if (!CurrentProjectFile.RenameScenario(origpath, newpath)) { //couldn't rename it in the project? happens when project not saved yet... //MessageBox.Show("Couldn't rename scenario in project! This shouldn't happen - check the project file XML."); } } SetProjectHasChanged(true); SetCurrentSaveItem(); } } private void AddScenarioToProject(YmtFile ymt) { if (ymt == null) return; if (CurrentProjectFile == null) { NewProject(); } if (ScenarioExistsInProject(ymt)) return; if (CurrentProjectFile.AddScenarioFile(ymt)) { ymt.HasChanged = true; CurrentProjectFile.HasChanged = true; LoadProjectTree(); } CurrentScenario = ymt; RefreshUI(); if (CurrentScenarioNode != null) { TrySelectScenarioNodeTreeNode(CurrentScenarioNode); } } private void RemoveScenarioFromProject() { if (CurrentScenario == null) return; if (CurrentProjectFile == null) return; CurrentProjectFile.RemoveScenarioFile(CurrentScenario); CurrentScenario = null; LoadProjectTree(); RefreshUI(); } private void LoadScenarioTabPage() { if (CurrentScenario == null) { populatingui = true; ScenarioYmtPanel.Enabled = false; ScenarioYmtNameTextBox.Text = string.Empty; ScenarioYmtVersionTextBox.Text = string.Empty; ScenarioYmtGridMinTextBox.Text = string.Empty; ScenarioYmtGridMaxTextBox.Text = string.Empty; ScenarioYmtGridScaleTextBox.Text = string.Empty; ScenarioYmtGridInfoLabel.Text = "Total grid points: 0"; ScenarioYmtExtentsMinTextBox.Text = string.Empty; ScenarioYmtExtentsMaxTextBox.Text = string.Empty; ScenarioYmtFileLocationTextBox.Text = string.Empty; ScenarioYmtProjectPathTextBox.Text = string.Empty; populatingui = false; } else { var rgn = CurrentScenario.CScenarioPointRegion; var accg = rgn?._Data.AccelGrid ?? new rage__spdGrid2D(); var bvh = CurrentScenario.ScenarioRegion?.BVH; var emin = bvh?.Box.Minimum ?? Vector3.Zero; var emax = bvh?.Box.Maximum ?? Vector3.Zero; populatingui = true; ScenarioYmtPanel.Enabled = true; ScenarioYmtNameTextBox.Text = CurrentScenario.Name; ScenarioYmtVersionTextBox.Text = rgn?.VersionNumber.ToString() ?? ""; ScenarioYmtGridMinTextBox.Text = FloatUtil.GetVector2String(accg.Min); ScenarioYmtGridMaxTextBox.Text = FloatUtil.GetVector2String(accg.Max); ScenarioYmtGridScaleTextBox.Text = FloatUtil.GetVector2String(accg.Scale); ScenarioYmtGridInfoLabel.Text = "Total grid points: " + (rgn?.Unk_3844724227?.Length ?? 0).ToString(); ScenarioYmtExtentsMinTextBox.Text = FloatUtil.GetVector3String(emin); ScenarioYmtExtentsMaxTextBox.Text = FloatUtil.GetVector3String(emax); ScenarioYmtFileLocationTextBox.Text = CurrentScenario.RpfFileEntry?.Path ?? ""; ScenarioYmtProjectPathTextBox.Text = (CurrentProjectFile != null) ? CurrentProjectFile.GetRelativePath(CurrentScenario.FilePath) : CurrentScenario.FilePath; populatingui = false; } } private void LoadScenarioFromFile(YmtFile ymt, string filename) { byte[] data = File.ReadAllBytes(filename); ymt.LoadRSC(data); } private void LoadScenarioTreeNodes(YmtFile ymt, TreeNode node) { if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Points node.Nodes.Clear(); var region = ymt?.ScenarioRegion; if (region == null) return; var nodes = region.Nodes; if ((nodes == null) || (nodes.Count == 0)) return; var pointsnode = node.Nodes.Add("Points (" + nodes.Count.ToString() + ")"); pointsnode.Name = "Points"; pointsnode.Tag = ymt; for (int i = 0; i < nodes.Count; i++) { var snode = nodes[i]; var tnode = pointsnode.Nodes.Add(snode.MedTypeName + ": " + snode.StringText); tnode.Tag = snode; } //var sr = region.Region; //if (sr == null) return; //int pointCount = (sr.Points?.LoadSavePoints?.Length ?? 0) + (sr.Points?.MyPoints?.Length ?? 0); //int entityOverrideCount = (sr.EntityOverrides?.Length ?? 0); //int chainCount = (sr.Paths?.Chains?.Length ?? 0); //int clusterCount = (sr.Clusters?.Length ?? 0); //TreeNode pointsNode = null; //TreeNode entityOverridesNode = null; //TreeNode chainsNode = null; //TreeNode clustersNode = null; //if (pointCount > 0) //{ // pointsNode = node.Nodes.Add("Points (" + pointCount.ToString() + ")"); //} //if (entityOverrideCount > 0) //{ // entityOverridesNode = node.Nodes.Add("Entity Overrides (" + entityOverrideCount.ToString() + ")"); //} //if (chainCount > 0) //{ // chainsNode = node.Nodes.Add("Chains (" + chainsNode.ToString() + ")"); //} //if (clusterCount > 0) //{ // clustersNode = node.Nodes.Add("Clusters (" + clusterCount.ToString() + ")"); //} //for (int i = 0; i < nodes.Count; i++) //{ // var snode = nodes[i]; // if (snode == null) continue; // if ((pointsNode != null) && ((snode.LoadSavePoint != null) || (snode.MyPoint != null))) // { // pointsNode.Nodes.Add(snode.ToString()).Tag = snode; // } // if ((entityOverridesNode != null) && ((snode.EntityOverride != null) || (snode.EntityPoint != null))) // { // entityOverridesNode.Nodes.Add(snode.ToString()).Tag = snode; // } // if ((chainsNode != null) && (snode.ChainingNode != null)) // { // chainsNode.Nodes.Add(snode.ToString()).Tag = snode; // } // if ((clustersNode != null) && ((snode.Cluster != null) || (snode.ClusterLoadSavePoint != null) || (snode.ClusterMyPoint != null))) // { // clustersNode.Nodes.Add(snode.ToString()).Tag = snode; // } //} } private void SetScenarioHasChanged(bool changed) { if (CurrentScenario == null) return; bool changechange = changed != CurrentScenario.HasChanged; if (!changechange) return; CurrentScenario.HasChanged = changed; SetScenarioHasChangedUI(changed); } private void SetScenarioHasChangedUI(bool changed) { if (ProjectTreeView.Nodes.Count > 0) { var pnode = ProjectTreeView.Nodes[0]; var scnode = GetChildTreeNode(pnode, "Scenarios"); if (scnode == null) return; string changestr = changed ? "*" : ""; for (int i = 0; i < scnode.Nodes.Count; i++) { var snode = scnode.Nodes[i]; if (snode.Tag == CurrentScenario) { string name = CurrentScenario.Name; if (CurrentScenario.RpfFileEntry != null) { name = CurrentScenario.RpfFileEntry.Name; } snode.Text = changestr + name; break; } } } } public void NewScenarioNode(ScenarioNode copy = null, bool copyPosition = false) { if (CurrentScenario == null) return; if (CurrentScenario.ScenarioRegion == null) return; if (copy == null) { copy = CurrentScenarioNode; } var n = CurrentScenario.ScenarioRegion.AddNode(copy); bool cp = copyPosition && (copy != null); Vector3 pos = cp ? copy.Position : GetSpawnPos(10.0f); Quaternion ori = cp ? copy.Orientation : Quaternion.Identity; n.SetPosition(pos); n.SetOrientation(ori); LoadProjectTree(); TrySelectScenarioNodeTreeNode(n); CurrentScenarioNode = n; LoadScenarioTabPage(); LoadScenarioNodeTabPages(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } public bool DeleteScenarioNode() { if (CurrentScenario == null) return false; if (CurrentScenario.ScenarioRegion == null) return false; if (CurrentScenarioNode == null) return false; if (MessageBox.Show("Are you sure you want to delete this scenario node?\n" + CurrentScenarioNode.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return true; } //find this now to remove it later. var tn = FindScenarioNodeTreeNode(CurrentScenarioNode); bool res = false; if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { res = CurrentScenario.ScenarioRegion.RemoveNode(CurrentScenarioNode); } } else { res = CurrentScenario.ScenarioRegion.RemoveNode(CurrentScenarioNode); } if (!res) { MessageBox.Show("Unable to delete the scenario node. This shouldn't happen!"); } SetScenarioHasChangedUI(true); CurrentScenarioNode = null; if ((tn != null) && (tn.Parent != null)) { tn.Parent.Text = "Points (" + (CurrentScenario?.ScenarioRegion?.Nodes?.Count ?? 0).ToString() + ")"; tn.Parent.Nodes.Remove(tn); } else { //no need for this when removing the node above will select something else. LoadScenarioNodeTabPages(); //this case really shouldn't happen... } if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } return true; } private void AddScenarioNodeToProject() { if (CurrentScenarioNode == null) return; if (CurrentScenario != null) { AddScenarioToProject(CurrentScenario); } } private void LoadScenarioNodeTabPages() { populatingui = true; LoadScenarioDropDowns(); LoadScenarioPointTabPage(); LoadScenarioEntityTabPage(); LoadScenarioEntityPointTabPage(); LoadScenarioChainTabPage(); LoadScenarioChainEdgeTabPage(); LoadScenarioChainNodeTabPage(); LoadScenarioClusterTabPage(); LoadScenarioClusterPointTabPage(); populatingui = false; if (CurrentScenarioNode != null) { if (WorldForm != null) { WorldForm.SelectScenarioNode(CurrentScenarioNode); } } } private void LoadScenarioDropDowns() { if (ScenarioPointTypeComboBox.Items.Count > 0) return; var types = Scenarios.ScenarioTypes; //these are loaded by Scenarios.Init if (types == null) { return; } var stypes = types.GetScenarioTypes(); if (stypes == null) return; var pmsets = types.GetPedModelSets(); if (pmsets == null) return; var vmsets = types.GetVehicleModelSets(); if (vmsets == null) return; ScenarioPointTypeComboBox.Items.Clear(); ScenarioPointTypeComboBox.Items.Add(""); ScenarioClusterPointTypeComboBox.Items.Clear(); ScenarioClusterPointTypeComboBox.Items.Add(""); ScenarioChainNodeTypeComboBox.Items.Clear(); ScenarioChainNodeTypeComboBox.Items.Add(""); foreach (var stype in stypes) { ScenarioPointTypeComboBox.Items.Add(stype); ScenarioClusterPointTypeComboBox.Items.Add(stype); ScenarioChainNodeTypeComboBox.Items.Add(stype); } ScenarioPointModelSetComboBox.Items.Clear(); ScenarioPointModelSetComboBox.Items.Add(""); ScenarioClusterPointModelSetComboBox.Items.Clear(); ScenarioClusterPointModelSetComboBox.Items.Add(""); foreach (var pmset in pmsets) { ScenarioPointModelSetComboBox.Items.Add(pmset); ScenarioClusterPointModelSetComboBox.Items.Add(pmset); } foreach (var vmset in vmsets) { ScenarioPointModelSetComboBox.Items.Add(vmset); ScenarioClusterPointModelSetComboBox.Items.Add(vmset); } ScenarioEntityPointAvailableInMpSpComboBox.Items.Clear(); ScenarioEntityPointAvailableInMpSpComboBox.Items.Add(Unk_3573596290.kBoth); ScenarioEntityPointAvailableInMpSpComboBox.Items.Add(Unk_3573596290.kOnlySp); ScenarioEntityPointAvailableInMpSpComboBox.Items.Add(Unk_3573596290.kOnlyMp); ScenarioChainEdgeActionComboBox.Items.Clear(); ScenarioChainEdgeActionComboBox.Items.Add(Unk_3609807418.Move); ScenarioChainEdgeActionComboBox.Items.Add(Unk_3609807418.Unk_7865678); ScenarioChainEdgeActionComboBox.Items.Add(Unk_3609807418.MoveFollowMaster); ScenarioChainEdgeNavModeComboBox.Items.Clear(); ScenarioChainEdgeNavModeComboBox.Items.Add(Unk_3971773454.Direct); ScenarioChainEdgeNavModeComboBox.Items.Add(Unk_3971773454.NavMesh); ScenarioChainEdgeNavModeComboBox.Items.Add(Unk_3971773454.Roads); ScenarioChainEdgeNavSpeedComboBox.Items.Clear(); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_00_3279574318); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_01_2212923970); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_02_4022799658); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_03_1425672334); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_04_957720931); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_05_3795195414); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_06_2834622009); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_07_1876554076); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_08_698543797); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_09_1544199634); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_10_2725613303); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_11_4033265820); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_12_3054809929); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_13_3911005380); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_14_3717649022); ScenarioChainEdgeNavSpeedComboBox.Items.Add(Unk_941086046.Unk_15_3356026130); } private void LoadScenarioPointTabPage() { var p = CurrentScenarioNode?.MyPoint; if (p == null) { ScenarioPointPanel.Enabled = false; ScenarioPointCheckBox.Checked = false; ScenarioPointAddToProjectButton.Enabled = false; ScenarioPointDeleteButton.Enabled = false; ScenarioPointPositionTextBox.Text = ""; ScenarioPointDirectionTextBox.Text = ""; ScenarioPointTypeComboBox.SelectedItem = null; ScenarioPointModelSetComboBox.SelectedItem = null; ScenarioPointInteriorTextBox.Text = ""; ScenarioPointInteriorHashLabel.Text = "Hash: 0"; ScenarioPointGroupTextBox.Text = ""; ScenarioPointGroupHashLabel.Text = "Hash: 0"; ScenarioPointImapTextBox.Text = ""; ScenarioPointImapHashLabel.Text = "Hash: 0"; ScenarioPointTimeStartUpDown.Value = 0; ScenarioPointTimeEndUpDown.Value = 0; ScenarioPointProbabilityUpDown.Value = 0; ScenarioPointSpOnlyFlagUpDown.Value = 0; ScenarioPointRadiusUpDown.Value = 0; ScenarioPointWaitTimeUpDown.Value = 0; ScenarioPointFlagsValueUpDown.Value = 0; foreach (int i in ScenarioPointFlagsCheckedListBox.CheckedIndices) { ScenarioPointFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); } } else { ScenarioPointPanel.Enabled = true; ScenarioPointCheckBox.Checked = true; ScenarioPointDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); ScenarioPointAddToProjectButton.Enabled = !ScenarioPointDeleteButton.Enabled; ScenarioPointPositionTextBox.Text = FloatUtil.GetVector3String(p.Position); ScenarioPointDirectionTextBox.Text = FloatUtil.ToString(p.Direction); ScenarioPointTypeComboBox.SelectedItem = ((object)p.Type) ?? ""; ScenarioPointModelSetComboBox.SelectedItem = ((object)p.ModelSet) ?? ""; ScenarioPointInteriorTextBox.Text = p.InteriorName.ToString(); ScenarioPointInteriorHashLabel.Text = "Hash: " + p.InteriorName.Hash.ToString(); ScenarioPointGroupTextBox.Text = p.GroupName.ToString(); ScenarioPointGroupHashLabel.Text = "Hash: " + p.GroupName.Hash.ToString(); ScenarioPointImapTextBox.Text = p.IMapName.ToString(); ScenarioPointImapHashLabel.Text = "Hash: " + p.IMapName.Hash.ToString(); ScenarioPointTimeStartUpDown.Value = p.TimeStart; ScenarioPointTimeEndUpDown.Value = p.TimeEnd; ScenarioPointProbabilityUpDown.Value = p.Probability; ScenarioPointSpOnlyFlagUpDown.Value = p.AvailableMpSp; ScenarioPointRadiusUpDown.Value = p.Radius; ScenarioPointWaitTimeUpDown.Value = p.WaitTime; var iflags = (int)p.Flags; ScenarioPointFlagsValueUpDown.Value = iflags; for (int i = 0; i < ScenarioPointFlagsCheckedListBox.Items.Count; i++) { var c = ((iflags & (1 << i)) > 0); ScenarioPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } } } private void LoadScenarioEntityTabPage() { var e = CurrentScenarioNode?.Entity; if (e == null) { ScenarioEntityPanel.Enabled = false; ScenarioEntityCheckBox.Checked = false; ScenarioEntityAddToProjectButton.Enabled = false; ScenarioEntityDeleteButton.Enabled = false; ScenarioEntityPositionTextBox.Text = ""; ScenarioEntityTypeTextBox.Text = ""; ScenarioEntityTypeHashLabel.Text = "Hash: 0"; ScenarioEntityUnk1UpDown.Value = 0; ScenarioEntityUnk2UpDown.Value = 0; ScenarioEntityInfoLabel.Text = "0 override points"; ScenarioEntityPointsListBox.Items.Clear(); ScenarioEntityAddPointButton.Enabled = false; } else { ScenarioEntityPanel.Enabled = true; ScenarioEntityCheckBox.Checked = true; ScenarioEntityDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); ScenarioEntityAddToProjectButton.Enabled = !ScenarioEntityDeleteButton.Enabled; ScenarioEntityPositionTextBox.Text = FloatUtil.GetVector3String(e.Position); ScenarioEntityTypeTextBox.Text = e.TypeName.ToString(); ScenarioEntityTypeHashLabel.Text = "Hash: " + e.TypeName.Hash.ToString(); ScenarioEntityUnk1UpDown.Value = e.Unk1; ScenarioEntityUnk2UpDown.Value = e.Unk2; var pc = e.ScenarioPoints?.Length ?? 0; ScenarioEntityInfoLabel.Text = pc.ToString() + " override point" + ((pc != 1) ? "s" : ""); ScenarioEntityPointsListBox.Items.Clear(); ScenarioEntityAddPointButton.Enabled = true; if (e.ScenarioPoints != null) { foreach (var point in e.ScenarioPoints) { ScenarioEntityPointsListBox.Items.Add(point); } if (CurrentScenarioNode.EntityPoint != null) { ScenarioEntityPointsListBox.SelectedItem = CurrentScenarioNode.EntityPoint; } } } } private void LoadScenarioEntityPointTabPage() { var p = CurrentScenarioNode?.EntityPoint; if (p == null) { ScenarioEntityPointPanel.Enabled = false; ScenarioEntityPointCheckBox.Checked = false; ScenarioEntityPointAddToProjectButton.Enabled = false; ScenarioEntityPointDeleteButton.Enabled = false; ScenarioEntityPointNameTextBox.Text = ""; ScenarioEntityPointNameHashLabel.Text = "Hash: 0"; ScenarioEntityPointPositionTextBox.Text = ""; ScenarioEntityPointRotationTextBox.Text = ""; ScenarioEntityPointSpawnTypeTextBox.Text = ""; ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: 0"; ScenarioEntityPointPedTypeTextBox.Text = ""; ScenarioEntityPointPedTypeHashLabel.Text = "Hash: 0"; ScenarioEntityPointGroupTextBox.Text = ""; ScenarioEntityPointGroupHashLabel.Text = "Hash: 0"; ScenarioEntityPointInteriorTextBox.Text = ""; ScenarioEntityPointInteriorHashLabel.Text = "Hash: 0"; ScenarioEntityPointRequiredImapTextBox.Text = ""; ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: 0"; ScenarioEntityPointAvailableInMpSpComboBox.SelectedItem = null; ScenarioEntityPointProbabilityTextBox.Text = ""; ScenarioEntityPointTimeTillPedLeavesTextBox.Text = ""; ScenarioEntityPointRadiusTextBox.Text = ""; ScenarioEntityPointStartUpDown.Value = 0; ScenarioEntityPointEndUpDown.Value = 0; ScenarioEntityPointExtendedRangeCheckBox.Checked = false; ScenarioEntityPointShortRangeCheckBox.Checked = false; ScenarioEntityPointHighPriCheckBox.Checked = false; ScenarioEntityPointFlagsUpDown.Value = 0; foreach (int i in ScenarioEntityPointFlagsCheckedListBox.CheckedIndices) { ScenarioEntityPointFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); } } else { ScenarioEntityPointPanel.Enabled = true; ScenarioEntityPointCheckBox.Checked = true; ScenarioEntityPointDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); ScenarioEntityPointAddToProjectButton.Enabled = !ScenarioEntityPointDeleteButton.Enabled; ScenarioEntityPointNameTextBox.Text = p.NameHash.ToString(); ScenarioEntityPointNameHashLabel.Text = "Hash: " + p.NameHash.Hash.ToString(); ScenarioEntityPointPositionTextBox.Text = FloatUtil.GetVector3String(p.OffsetPosition); ScenarioEntityPointRotationTextBox.Text = FloatUtil.GetVector4String(p.OffsetRotation); ScenarioEntityPointSpawnTypeTextBox.Text = p.SpawnType.ToString(); ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: " + p.SpawnType.Hash.ToString(); ScenarioEntityPointPedTypeTextBox.Text = p.PedType.ToString(); ScenarioEntityPointPedTypeHashLabel.Text = "Hash: " + p.PedType.Hash.ToString(); ScenarioEntityPointGroupTextBox.Text = p.Group.ToString(); ScenarioEntityPointGroupHashLabel.Text = "Hash: " + p.Group.Hash.ToString(); ScenarioEntityPointInteriorTextBox.Text = p.Interior.ToString(); ScenarioEntityPointInteriorHashLabel.Text = "Hash: " + p.Interior.Hash.ToString(); ScenarioEntityPointRequiredImapTextBox.Text = p.RequiredImap.ToString(); ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: " + p.RequiredImap.Hash.ToString(); ScenarioEntityPointAvailableInMpSpComboBox.SelectedItem = p.AvailableInMpSp; ScenarioEntityPointProbabilityTextBox.Text = FloatUtil.ToString(p.Probability); ScenarioEntityPointTimeTillPedLeavesTextBox.Text = FloatUtil.ToString(p.TimeTillPedLeaves); ScenarioEntityPointRadiusTextBox.Text = FloatUtil.ToString(p.Radius); ScenarioEntityPointStartUpDown.Value = p.StartTime; ScenarioEntityPointEndUpDown.Value = p.EndTime; ScenarioEntityPointExtendedRangeCheckBox.Checked = p.ExtendedRange; ScenarioEntityPointShortRangeCheckBox.Checked = p.ShortRange; ScenarioEntityPointHighPriCheckBox.Checked = p.HighPri; var iflags = (int)p.Flags; ScenarioEntityPointFlagsUpDown.Value = 0; for (int i = 0; i < ScenarioEntityPointFlagsCheckedListBox.Items.Count; i++) { var c = ((iflags & (1 << i)) > 0); ScenarioEntityPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } } } private void LoadScenarioChainTabPage() { CurrentScenarioChainEdge = null; var n = CurrentScenarioNode?.ChainingNode; if (n == null) { ScenarioChainAddToProjectButton.Enabled = false; ScenarioChainDeleteButton.Enabled = false; ScenarioChainEdgesListBox.Items.Clear(); ScenarioChainEdgeCountLabel.Text = "Edge Count: 0"; ScenarioChainUnk1UpDown.Value = 0; } else { ScenarioChainDeleteButton.Enabled = ScenarioChainNodeDeleteButton.Enabled;// ScenarioExistsInProject(CurrentScenario); ScenarioChainAddToProjectButton.Enabled = !ScenarioChainDeleteButton.Enabled; ScenarioChainEdgesListBox.Items.Clear(); ScenarioChainEdgeCountLabel.Text = "Edge Count: " + (n.Chain?.EdgeIds?.Length ?? 0).ToString(); ScenarioChainUnk1UpDown.Value = n.Chain?.Unk1 ?? 0; if ((n.Chain != null) && (n.Chain.Edges != null)) { foreach (var edge in n.Chain.Edges) { ScenarioChainEdgesListBox.Items.Add(edge); } } else { } } } private void LoadScenarioChainEdgeTabPage() { var e = CurrentScenarioChainEdge; if (e == null) { ScenarioChainEdgePanel.Enabled = false; ScenarioChainEdgeNodeIndexFromUpDown.Value = 0; ScenarioChainEdgeNodeIndexToUpDown.Value = 0; ScenarioChainEdgeActionComboBox.SelectedItem = null; ScenarioChainEdgeNavModeComboBox.SelectedItem = null; ScenarioChainEdgeNavSpeedComboBox.SelectedItem = null; ScenarioChainMoveEdgeDownButton.Enabled = false; ScenarioChainMoveEdgeUpButton.Enabled = false; } else { ScenarioChainEdgePanel.Enabled = true; ScenarioChainEdgeNodeIndexFromUpDown.Value = e.NodeIndexFrom; ScenarioChainEdgeNodeIndexToUpDown.Value = e.NodeIndexTo; ScenarioChainEdgeActionComboBox.SelectedItem = e.Action; ScenarioChainEdgeNavModeComboBox.SelectedItem = e.NavMode; ScenarioChainEdgeNavSpeedComboBox.SelectedItem = e.NavSpeed; ScenarioChainMoveEdgeDownButton.Enabled = true; ScenarioChainMoveEdgeUpButton.Enabled = true; if (WorldForm != null) { WorldForm.SelectScenarioEdge(CurrentScenarioNode, e); } } } private void LoadScenarioChainNodeTabPage() { var n = CurrentScenarioNode?.ChainingNode; if (n == null) { ScenarioChainNodePanel.Enabled = false; ScenarioChainNodeCheckBox.Checked = false; ScenarioChainNodeAddToProjectButton.Enabled = false; ScenarioChainNodeDeleteButton.Enabled = false; ScenarioChainNodePositionTextBox.Text = ""; ScenarioChainNodeUnk1TextBox.Text = ""; ScenarioChainNodeUnk1HashLabel.Text = "Hash: 0"; ScenarioChainNodeTypeComboBox.SelectedItem = null; ScenarioChainNodeFirstCheckBox.Checked = false; ScenarioChainNodeLastCheckBox.Checked = false; ScenarioChainNodeIndexTextBox.Text = ""; } else { ScenarioChainNodePanel.Enabled = true; ScenarioChainNodeCheckBox.Checked = true; ScenarioChainNodeDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); ScenarioChainNodeAddToProjectButton.Enabled = !ScenarioChainNodeDeleteButton.Enabled; ScenarioChainNodePositionTextBox.Text = FloatUtil.GetVector3String(n.Position); ScenarioChainNodeUnk1TextBox.Text = n.Unk1.ToString(); ScenarioChainNodeUnk1HashLabel.Text = "Hash: " + n.Unk1.Hash.ToString(); ScenarioChainNodeTypeComboBox.SelectedItem = ((object)n.Type) ?? ""; ScenarioChainNodeFirstCheckBox.Checked = !n.NotFirst; ScenarioChainNodeLastCheckBox.Checked = !n.NotLast; ScenarioChainNodeIndexTextBox.Text = n.NodeIndex.ToString(); } } private void LoadScenarioClusterTabPage() { var c = CurrentScenarioNode?.Cluster; if (c == null) { ScenarioClusterPanel.Enabled = false; ScenarioClusterCheckBox.Checked = false; ScenarioClusterAddToProjectButton.Enabled = false; ScenarioClusterDeleteButton.Enabled = false; ScenarioClusterCenterTextBox.Text = ""; ScenarioClusterRadiusTextBox.Text = ""; ScenarioClusterUnk1TextBox.Text = ""; ScenarioClusterUnk2CheckBox.Checked = false; ScenarioClusterPointsListBox.Items.Clear(); ScenarioClusterAddPointButton.Enabled = false; } else { ScenarioClusterPanel.Enabled = true; ScenarioClusterCheckBox.Checked = true; ScenarioClusterDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); ScenarioClusterAddToProjectButton.Enabled = !ScenarioClusterDeleteButton.Enabled; ScenarioClusterCenterTextBox.Text = FloatUtil.GetVector3String(c.Position); ScenarioClusterRadiusTextBox.Text = FloatUtil.ToString(c.Radius); ScenarioClusterUnk1TextBox.Text = FloatUtil.ToString(c.Unk1); ScenarioClusterUnk2CheckBox.Checked = c.Unk2; ScenarioClusterPointsListBox.Items.Clear(); ScenarioClusterAddPointButton.Enabled = true; if (c.Points != null) { if (c.Points.MyPoints != null) { foreach (var point in c.Points.MyPoints) { ScenarioClusterPointsListBox.Items.Add(point); } if (CurrentScenarioNode.ClusterMyPoint != null) { ScenarioClusterPointsListBox.SelectedItem = CurrentScenarioNode.ClusterMyPoint; } } if (c.Points.LoadSavePoints != null) { foreach (var point in c.Points.LoadSavePoints) { ScenarioClusterPointsListBox.Items.Add(point); } if (CurrentScenarioNode.ClusterLoadSavePoint != null) { ScenarioClusterPointsListBox.SelectedItem = CurrentScenarioNode.ClusterLoadSavePoint; } } } } } private void LoadScenarioClusterPointTabPage() { var p = CurrentScenarioNode?.ClusterMyPoint; if (p == null) { ScenarioClusterPointPanel.Enabled = false; ScenarioClusterPointCheckBox.Checked = false; ScenarioClusterPointAddToProjectButton.Enabled = false; ScenarioClusterPointDeleteButton.Enabled = false; ScenarioClusterPointPositionTextBox.Text = ""; ScenarioClusterPointDirectionTextBox.Text = ""; ScenarioClusterPointTypeComboBox.SelectedItem = null; ScenarioClusterPointModelSetComboBox.SelectedItem = null; ScenarioClusterPointInteriorTextBox.Text = ""; ScenarioClusterPointInteriorHashLabel.Text = "Hash: 0"; ScenarioClusterPointGroupTextBox.Text = ""; ScenarioClusterPointGroupHashLabel.Text = "Hash: 0"; ScenarioClusterPointImapTextBox.Text = ""; ScenarioClusterPointImapHashLabel.Text = "Hash: 0"; ScenarioClusterPointTimeStartUpDown.Value = 0; ScenarioClusterPointTimeEndUpDown.Value = 0; ScenarioClusterPointProbabilityUpDown.Value = 0; ScenarioClusterPointAnimalFlagUpDown.Value = 0; ScenarioClusterPointRadiusUpDown.Value = 0; ScenarioClusterPointWaitTimeUpDown.Value = 0; ScenarioClusterPointFlagsUpDown.Value = 0; foreach (int i in ScenarioClusterPointFlagsCheckedListBox.CheckedIndices) { ScenarioClusterPointFlagsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked); } } else { ScenarioClusterPointPanel.Enabled = true; ScenarioClusterPointCheckBox.Checked = true; ScenarioClusterPointDeleteButton.Enabled = ScenarioExistsInProject(CurrentScenario); ScenarioClusterPointAddToProjectButton.Enabled = !ScenarioClusterPointDeleteButton.Enabled; ScenarioClusterPointPositionTextBox.Text = FloatUtil.GetVector3String(p.Position); ScenarioClusterPointDirectionTextBox.Text = FloatUtil.ToString(p.Direction); ScenarioClusterPointTypeComboBox.SelectedItem = ((object)p.Type) ?? ""; ScenarioClusterPointModelSetComboBox.SelectedItem = ((object)p.ModelSet) ?? ""; ScenarioClusterPointInteriorTextBox.Text = p.InteriorName.ToString(); ScenarioClusterPointInteriorHashLabel.Text = "Hash: " + p.InteriorName.Hash.ToString(); ScenarioClusterPointGroupTextBox.Text = p.GroupName.ToString(); ScenarioClusterPointGroupHashLabel.Text = "Hash: " + p.GroupName.Hash.ToString(); ScenarioClusterPointImapTextBox.Text = p.IMapName.ToString(); ScenarioClusterPointImapHashLabel.Text = "Hash: " + p.IMapName.Hash.ToString(); ScenarioClusterPointTimeStartUpDown.Value = p.TimeStart; ScenarioClusterPointTimeEndUpDown.Value = p.TimeEnd; ScenarioClusterPointProbabilityUpDown.Value = p.Probability; ScenarioClusterPointAnimalFlagUpDown.Value = p.AvailableMpSp; ScenarioClusterPointRadiusUpDown.Value = p.Radius; ScenarioClusterPointWaitTimeUpDown.Value = p.WaitTime; var iflags = (int)p.Flags; ScenarioClusterPointFlagsUpDown.Value = iflags; for (int i = 0; i < ScenarioClusterPointFlagsCheckedListBox.Items.Count; i++) { var c = ((iflags & (1 << i)) > 0); ScenarioClusterPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } } } private void SelectScenarioNodeTabPages(ScenarioNode node) { //select the appropriate tab page(s) for the given node. if (node == null) return; bool reseltree = ProjectTreeView.Focused; bool change = false; if (node.MyPoint != null) { bool sw = true; if ((node.Entity != null) && (ScenarioTabControl.SelectedTab == ScenarioEntityTabPage)) { sw = false; } if ((node.EntityPoint != null) && (ScenarioTabControl.SelectedTab == ScenarioEntityPointTabPage)) { sw = false; } if ((node.Cluster != null) && (ScenarioTabControl.SelectedTab == ScenarioClusterTabPage)) { sw = false; } if ((node.ClusterMyPoint != null) && (ScenarioTabControl.SelectedTab == ScenarioClusterPointTabPage)) { sw = false; } if ((node.ChainingNode != null) && (ScenarioTabControl.SelectedTab == ScenarioChainTabPage)) { sw = false; } if ((node.ChainingNode != null) && (ScenarioTabControl.SelectedTab == ScenarioChainNodeTabPage)) { sw = false; } if (sw) { change = ScenarioTabControl.SelectedTab != ScenarioPointTabPage; ScenarioTabControl.SelectedTab = ScenarioPointTabPage; } } else if (node.EntityPoint != null) { if (ScenarioTabControl.SelectedTab != ScenarioEntityTabPage) { change = ScenarioTabControl.SelectedTab != ScenarioEntityPointTabPage; ScenarioTabControl.SelectedTab = ScenarioEntityPointTabPage; } } else if (node.Entity != null) { change = ScenarioTabControl.SelectedTab != ScenarioEntityTabPage; ScenarioTabControl.SelectedTab = ScenarioEntityTabPage; } else if (node.ClusterMyPoint != null) { if (ScenarioTabControl.SelectedTab != ScenarioClusterTabPage) { change = ScenarioTabControl.SelectedTab != ScenarioClusterPointTabPage; ScenarioTabControl.SelectedTab = ScenarioClusterPointTabPage; } } else if (node.Cluster != null) { change = ScenarioTabControl.SelectedTab != ScenarioClusterTabPage; ScenarioTabControl.SelectedTab = ScenarioClusterTabPage; } else if (node.ChainingNode != null) { if (ScenarioTabControl.SelectedTab != ScenarioChainTabPage) { change = ScenarioTabControl.SelectedTab != ScenarioChainNodeTabPage; ScenarioTabControl.SelectedTab = ScenarioChainNodeTabPage; } } else //if (node.MyPoint != null) { change = ScenarioTabControl.SelectedTab != ScenarioPointTabPage; ScenarioTabControl.SelectedTab = ScenarioPointTabPage; } if (reseltree && change) { ProjectTreeView.Focus(); } } public bool IsCurrentScenarioNode(ScenarioNode node) { return node == CurrentScenarioNode; } private void AddScenarioChain() { if (CurrentScenario.ScenarioRegion == null) return; var paths = CurrentScenario?.CScenarioPointRegion?.Paths; if (paths == null) return; var copy = CurrentScenarioNode?.ChainingNode?.Chain; var copyn = CurrentScenarioNode?.ChainingNode; var copyp = CurrentScenarioNode?.MyPoint; var copye = CurrentScenarioChainEdge; var copycl = CurrentScenarioNode?.Cluster; MCScenarioChain chain = new MCScenarioChain(); chain.Unk1 = 1; //default value if (copy != null) { chain.Data = copy.Data; chain._Data.EdgeIds = new Array_ushort(); //start empty.. not really necessary } paths.AddChain(chain); //add 2 new nodes to the new chain. var pos1 = GetSpawnPos(10.0f); var pos2 = pos1 + Vector3.UnitX; ScenarioNode n1 = null;// CurrentScenario.ScenarioRegion.AddNode(); if (copycl != null) { ScenarioNode copyclnode = new ScenarioNode(CurrentScenario); copyclnode.Cluster = copycl; copyclnode.ClusterMyPoint = new MCScenarioPoint(CurrentScenario.CScenarioPointRegion); copyclnode.ClusterMyPoint.InteriorName = 493038497; //JenkHash.GenHash("none"); copyclnode.ClusterMyPoint.GroupName = 493038497; copyclnode.ClusterMyPoint.IMapName = 493038497; copyclnode.ClusterMyPoint.TimeStart = 0; copyclnode.ClusterMyPoint.TimeEnd = 24; n1 = CurrentScenario.ScenarioRegion.AddNode(copyclnode); } else { n1 = CurrentScenario.ScenarioRegion.AddNode(); } ScenarioNode n2 = CurrentScenario.ScenarioRegion.AddNode(); if (copyp != null) { n1.MyPoint.CopyFrom(copyp); n2.MyPoint.CopyFrom(copyp); } n1.ChainingNode = new MCScenarioChainingNode(); n2.ChainingNode = new MCScenarioChainingNode(); if (copyn != null) { n1.ChainingNode.CopyFrom(copyn); n2.ChainingNode.CopyFrom(copyn); } n1.ChainingNode.NotLast = true; n2.ChainingNode.NotFirst = true; n1.ChainingNode.ScenarioNode = n1; n2.ChainingNode.ScenarioNode = n2; paths.AddNode(n1.ChainingNode); paths.AddNode(n2.ChainingNode); n1.ChainingNode.Chain = chain; n2.ChainingNode.Chain = chain; var ed = new MCScenarioChainingEdge(); if (copye != null) { ed.Data = copye.Data; } ed.NodeFrom = n1.ChainingNode; ed.NodeTo = n2.ChainingNode; ed.NodeIndexFrom = (ushort)n1.ChainingNode.NodeIndex; ed.NodeIndexTo = (ushort)n2.ChainingNode.NodeIndex; paths.AddEdge(ed); chain.AddEdge(ed); n1.SetPosition(pos1); n2.SetPosition(pos2); LoadProjectTree(); TrySelectScenarioNodeTreeNode(n1); CurrentScenarioNode = n1; CurrentScenarioChainEdge = ed; LoadScenarioChainTabPage(); //LoadScenarioTabPage(); //LoadScenarioNodeTabPages(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } private void AddScenarioEdge() { var chain = CurrentScenarioNode?.ChainingNode?.Chain; if (chain == null) return; var paths = CurrentScenario?.CScenarioPointRegion?.Paths; if (paths == null) return; MCScenarioChainingEdge edge = new MCScenarioChainingEdge(); if (CurrentScenarioChainEdge != null) { edge.Data = CurrentScenarioChainEdge.Data; } paths.AddEdge(edge); chain.AddEdge(edge); CurrentScenarioChainEdge = edge; UpdateScenarioEdgeLinkage(); LoadScenarioChainTabPage(); ScenarioChainEdgesListBox.SelectedItem = edge; } private void RemoveScenarioEdge() { if (CurrentScenarioChainEdge == null) return; if (CurrentScenario == null) return; var chain = CurrentScenarioNode?.ChainingNode?.Chain; if (chain == null) return; var paths = CurrentScenario?.CScenarioPointRegion?.Paths; if (paths == null) return; if (MessageBox.Show("Are you sure you want to delete this scenario chain edge?\n" + CurrentScenarioChainEdge.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } chain.RemoveEdge(CurrentScenarioChainEdge); paths.RemoveEdge(CurrentScenarioChainEdge); LoadScenarioChainTabPage(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); WorldForm.SelectScenarioEdge(CurrentScenarioNode, null); } } private void MoveScenarioEdge(bool moveDown) { var chain = CurrentScenarioNode?.ChainingNode?.Chain; if (chain == null) return; if (chain.Edges == null) return; if (chain.EdgeIds == null) return; if (CurrentScenarioChainEdge == null) return; var edges = CurrentScenario?.CScenarioPointRegion?.Paths?.Edges; if (edges == null) return; int lasti = (chain.Edges?.Length ?? 0) - 1; var edgeid = 0; for (int i = 0; i < chain.Edges.Length; i++) { if (chain.Edges[i] == CurrentScenarioChainEdge) { edgeid = i; break; } } if (!moveDown && (edgeid <= 0)) return; if (moveDown && (edgeid >= lasti)) return; var swapid = edgeid + (moveDown ? 1 : -1); var swaped = chain.Edges[swapid]; chain.Edges[swapid] = CurrentScenarioChainEdge; chain.EdgeIds[swapid] = (ushort)CurrentScenarioChainEdge.EdgeIndex; chain.Edges[edgeid] = swaped; chain.EdgeIds[edgeid] = (ushort)swapid; var ce = CurrentScenarioChainEdge; LoadScenarioChainTabPage(); CurrentScenarioChainEdge = ce; ScenarioChainEdgesListBox.SelectedItem = ce; //LoadScenarioChainEdgeTabPage(); } private void UpdateScenarioEdgeLinkage() { if (CurrentScenarioChainEdge == null) return; if (CurrentScenario == null) return; var chains = CurrentScenario?.CScenarioPointRegion?.Paths; if (chains == null) return; var nodes = chains.Nodes; if (nodes == null) return; ushort nifrom = CurrentScenarioChainEdge.NodeIndexFrom; ushort nito = CurrentScenarioChainEdge.NodeIndexTo; if (nifrom < nodes.Length) CurrentScenarioChainEdge.NodeFrom = nodes[nifrom]; if (nito < nodes.Length) CurrentScenarioChainEdge.NodeTo = nodes[nito]; ////need to rebuild the link verts.. updating the graphics should do it... if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } private void DeleteScenarioChain() { if (CurrentScenario == null) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ChainingNode == null) return; if (CurrentScenarioNode.ChainingNode.Chain == null) return; var chain = CurrentScenarioNode.ChainingNode.Chain; var paths = CurrentScenario.CScenarioPointRegion?.Paths; if (paths == null) return; var rgn = CurrentScenario.ScenarioRegion; if (rgn == null) return; if (MessageBox.Show("Are you sure you want to delete this scenario chain?\n" + chain.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } bool delpoints = false; if (MessageBox.Show("Delete all Scenario Points for this chain as well?", "Confirm delete points", MessageBoxButtons.YesNo) == DialogResult.Yes) { delpoints = true; } Dictionary ndict = new Dictionary(); var edges = chain.Edges; if (edges != null) { foreach (var edge in edges) { //paths.RemoveEdge(edge); //removing nodes also removes edges! paths.RemoveNode(edge.NodeFrom); paths.RemoveNode(edge.NodeTo); ndict[edge.NodeFrom] = 1; ndict[edge.NodeTo] = 1; } } paths.RemoveChain(chain); List delnodes = new List(); foreach (var node in rgn.Nodes) { if ((node.ChainingNode != null) && (ndict.ContainsKey(node.ChainingNode))) { delnodes.Add(node); } } foreach (var delnode in delnodes) { delnode.ChainingNode = null;//this chaining node has been removed from the region. remove this association. if (delpoints) { rgn.RemoveNode(delnode); } } var cn = CurrentScenarioNode; var cs = CurrentScenario; LoadProjectTree(); if (!delpoints && (cn != null)) { TrySelectScenarioNodeTreeNode(cn); } else { TrySelectScenarioTreeNode(cs); } if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(cs, false); if (delpoints) { WorldForm.SelectItem(null); } } else if (cs?.ScenarioRegion != null) { cs.ScenarioRegion.BuildBVH(); cs.ScenarioRegion.BuildVertices(); //for the graphics... } } private void AddScenarioCluster()//TODO: add defualt cluster points to new cluster { if (CurrentScenario == null) return; var sr = CurrentScenario.ScenarioRegion; if (sr == null) return; var rgn = CurrentScenario.CScenarioPointRegion; if (rgn == null) return; var copy = CurrentScenarioNode?.Cluster; MCScenarioPointCluster cluster = new MCScenarioPointCluster(rgn, copy); List clusterpoints = new List(); if (copy != null) { if (copy.Points?.MyPoints != null) { clusterpoints.AddRange(copy.Points.MyPoints); } } rgn.AddCluster(cluster); //add the base cluster to the region. var pos1 = GetSpawnPos(10.0f); var ncopy = new ScenarioNode(CurrentScenario);//copy an empty node to start with, to avoid creating default MyPoint var nc = sr.AddNode(ncopy); //add the base cluster's display node. nc.Cluster = cluster; nc.SetPosition(pos1); if (cluster.Points != null) { foreach (var cpt in clusterpoints) { //TODO: copy cluster points.... //or create some default points! } } LoadProjectTree(); TrySelectScenarioNodeTreeNode(nc); CurrentScenarioNode = nc; LoadScenarioClusterTabPage(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } private void DeleteScenarioCluster() { if (CurrentScenario == null) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Cluster == null) return; var cluster = CurrentScenarioNode.Cluster; var rgn = CurrentScenario.ScenarioRegion; if (rgn == null) return; var crgn = CurrentScenario.CScenarioPointRegion; if (crgn == null) return; if (MessageBox.Show("Are you sure you want to delete this scenario cluster?\n" + cluster.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } bool delpoints = false; if (MessageBox.Show("Delete all Scenario Points for this cluster as well?", "Confirm delete points", MessageBoxButtons.YesNo) == DialogResult.Yes) { delpoints = true; } crgn.RemoveCluster(cluster); Dictionary ndict = new Dictionary(); if (cluster?.Points?.MyPoints != null) { foreach (var point in cluster.Points.MyPoints) { ndict[point] = 1; } } List delnodes = new List(); foreach (var node in rgn.Nodes) { if ((node.ClusterMyPoint != null) && (ndict.ContainsKey(node.ClusterMyPoint))) { delnodes.Add(node); } else if (node.Cluster == cluster) { delnodes.Add(node); } } foreach (var delnode in delnodes) { if (!delpoints && (crgn.Points != null) && (delnode.ClusterMyPoint != null)) { var copypt = new MCScenarioPoint(crgn, delnode.ClusterMyPoint); crgn.Points.AddMyPoint(copypt); delnode.MyPoint = copypt; } bool iscl = false; if ((delnode.Cluster != null) && (delnode.ClusterMyPoint == null) && (delnode.ClusterLoadSavePoint == null)) { iscl = true; } delnode.Cluster = null; delnode.ClusterMyPoint = null;//this cluster point has been removed from the region. remove this association. delnode.ClusterLoadSavePoint = null; if (delpoints) { //if ((delnode.ChainingNode == null) && (delnode.EntityPoint == null)) { rgn.RemoveNode(delnode); } } else if (iscl) { rgn.RemoveNode(delnode); //remove the cluster node itself. } } var cn = CurrentScenarioNode; var cs = CurrentScenario; LoadProjectTree(); if (!delpoints && (cn != null)) { TrySelectScenarioNodeTreeNode(cn); } else { TrySelectScenarioTreeNode(cs); } if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(cs, false); if (delpoints || ((cn != null) && (cn.MyPoint == null))) { WorldForm.SelectItem(null); } } else if (cs?.ScenarioRegion != null) { cs.ScenarioRegion.BuildBVH(); cs.ScenarioRegion.BuildVertices(); //for the graphics... } } private void AddScenarioClusterPoint() { if (CurrentScenario == null) return; var sr = CurrentScenario.ScenarioRegion; if (sr == null) return; var rgn = CurrentScenario.CScenarioPointRegion; if (rgn == null) return; var cluster = CurrentScenarioNode?.Cluster; if (cluster == null) return; if (cluster.Points == null) { cluster.Points = new MCScenarioPointContainer(rgn); cluster.Points.Parent = cluster; } var copy = CurrentScenarioNode?.ClusterMyPoint; var pos1 = GetSpawnPos(10.0f); var ori1 = copy?.Orientation ?? Quaternion.Identity; var cn = new ScenarioNode(CurrentScenario);//copy a blank node var n = sr.AddNode(cn); var np = new MCScenarioPoint(rgn, copy); cluster.Points.AddMyPoint(np); n.ClusterMyPoint = np; n.Cluster = cluster; n.SetPosition(pos1); n.SetOrientation(ori1); LoadProjectTree(); TrySelectScenarioNodeTreeNode(n); CurrentScenarioNode = n; LoadScenarioClusterTabPage(); LoadScenarioClusterPointTabPage(); //LoadScenarioTabPage(); //LoadScenarioNodeTabPages(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } private void AddScenarioEntity()//TODO: add default entity point(s) to entity { if (CurrentScenario == null) return; var sr = CurrentScenario.ScenarioRegion; if (sr == null) return; var rgn = CurrentScenario.CScenarioPointRegion; if (rgn == null) return; var copy = CurrentScenarioNode?.Entity; MCScenarioEntityOverride entity = new MCScenarioEntityOverride(rgn, copy); List entpoints = new List(); if (copy != null) { if (copy.ScenarioPoints != null) { entpoints.AddRange(copy.ScenarioPoints); } } rgn.AddEntity(entity); //add the base entity to the region. var pos1 = GetSpawnPos(10.0f); var ncopy = new ScenarioNode(CurrentScenario);//copy an empty node to start with, to avoid creating default MyPoint var ne = sr.AddNode(ncopy); //add the base entity's display node. ne.Entity = entity; ne.SetPosition(pos1); if (entity.ScenarioPoints != null) { foreach (var cpt in entpoints) { //TODO: copy entity points.... //or create some default points! } } LoadProjectTree(); TrySelectScenarioNodeTreeNode(ne); CurrentScenarioNode = ne; LoadScenarioEntityTabPage(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } private void DeleteScenarioEntity() { if (CurrentScenario == null) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Entity == null) return; var entity = CurrentScenarioNode.Entity; var rgn = CurrentScenario.ScenarioRegion; if (rgn == null) return; var crgn = CurrentScenario.CScenarioPointRegion; if (crgn == null) return; if (MessageBox.Show("Are you sure you want to delete this scenario entity override, and all its override points?\n" + entity.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes) { return; } //bool delpoints = false; //if (MessageBox.Show("Delete all Scenario Points for this entity override as well?", "Confirm delete points", MessageBoxButtons.YesNo) == DialogResult.Yes) //{ // delpoints = true; //} crgn.RemoveEntity(entity); Dictionary ndict = new Dictionary(); if (entity.ScenarioPoints != null) { foreach (var point in entity.ScenarioPoints) { ndict[point] = 1; } } List delnodes = new List(); foreach (var node in rgn.Nodes) { if ((node.EntityPoint != null) && (ndict.ContainsKey(node.EntityPoint))) { delnodes.Add(node); } else if (node.Entity == entity) { delnodes.Add(node); } } foreach (var delnode in delnodes) { delnode.Entity = null; delnode.EntityPoint = null;//this entity point has been removed from the region. remove this association. rgn.RemoveNode(delnode); } var cn = CurrentScenarioNode; var cs = CurrentScenario; LoadProjectTree(); TrySelectScenarioTreeNode(cs); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(cs, false); WorldForm.SelectItem(null); } else if (cs?.ScenarioRegion != null) { cs.ScenarioRegion.BuildBVH(); cs.ScenarioRegion.BuildVertices(); //for the graphics... } } private void AddScenarioEntityPoint() { if (CurrentScenario == null) return; var sr = CurrentScenario.ScenarioRegion; if (sr == null) return; var rgn = CurrentScenario.CScenarioPointRegion; if (rgn == null) return; var entity = CurrentScenarioNode?.Entity; if (entity == null) return; var copy = CurrentScenarioNode?.EntityPoint; var pos1 = GetSpawnPos(10.0f); var ori1 = copy?.Orientation ?? Quaternion.Identity; var cn = new ScenarioNode(CurrentScenario);//copy a blank node var n = sr.AddNode(cn); var np = new MCExtensionDefSpawnPoint(rgn, copy); entity.AddScenarioPoint(np); n.EntityPoint = np; n.Entity = entity; n.SetPosition(pos1); n.SetOrientation(ori1); LoadProjectTree(); TrySelectScenarioNodeTreeNode(n); CurrentScenarioNode = n; LoadScenarioEntityTabPage(); LoadScenarioEntityPointTabPage(); //LoadScenarioTabPage(); //LoadScenarioNodeTabPages(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } private void ImportScenarioChain() { var paths = CurrentScenario?.CScenarioPointRegion?.Paths; if (paths == null) return; var rgn = CurrentScenario.ScenarioRegion; if (rgn == null) return; TextInputForm f = new TextInputForm(); f.TitleText = "Import scenario chain points"; f.PromptText = "Input chain points in CSV (or TSV) format. Direction is in radians. NavSpeed is from 0 to 15. NavMode can be either Direct, NavMesh, or Roads. ScenarioType is the name of the scenario type to use."; f.MainText = "X, Y, Z, Direction, NavSpeed, NavMode, ScenarioType, ModelSet, Flags"; if (f.ShowDialog() == DialogResult.Cancel) return; var stypes = Scenarios.ScenarioTypes; //these are loaded by Scenarios.Init ScenarioType defaulttype = null; if (stypes != null) { defaulttype = stypes.GetScenarioType(1194480618); //"drive"; } AmbientModelSet defaultmodelset = null; uint defaultflags = 0; ScenarioNode thisnode = null; ScenarioNode lastnode = null; MCScenarioChainingEdge lastedge = null; var str = f.MainText; var lines = str.Split('\n'); if (lines.Length < 2) { return;//need at least 2 lines (1 point) to work with... } MCScenarioChain chain = new MCScenarioChain(); paths.AddChain(chain); for (int i = 0; i < lines.Length; i++) { var line = lines[i]; var delim = line.Contains(",") ? "," : " "; var vals = line.Split(new[] { delim }, StringSplitOptions.RemoveEmptyEntries); if (vals.Length < 3) continue; if (vals[0].StartsWith("X")) continue; Vector3 pos = Vector3.Zero; float dir = 0; var action = Unk_3609807418.Move; var navMode = Unk_3971773454.Direct; var navSpeed = Unk_941086046.Unk_00_3279574318; var stype = defaulttype; var modelset = defaultmodelset; var flags = defaultflags; var ok = true; ok = ok && FloatUtil.TryParse(vals[0].Trim(), out pos.X); ok = ok && FloatUtil.TryParse(vals[1].Trim(), out pos.Y); ok = ok && FloatUtil.TryParse(vals[2].Trim(), out pos.Z); if (vals.Length > 3) { ok = ok && FloatUtil.TryParse(vals[3].Trim(), out dir); while (dir > Math.PI) dir -= 2.0f * (float)Math.PI; while (dir < -Math.PI) dir += 2.0f * (float)Math.PI; } if (vals.Length > 4) { byte nsb = 0; byte.TryParse(vals[4].Trim(), out nsb); if (nsb > 15) nsb = 15; navSpeed = (Unk_941086046)nsb; } if (vals.Length > 5) { switch (vals[5].Trim()) { case "Direct": navMode = Unk_3971773454.Direct; break; case "NavMesh": navMode = Unk_3971773454.NavMesh; break; case "Roads": navMode = Unk_3971773454.Roads; break; } } if (vals.Length > 6) { var sthash = JenkHash.GenHash(vals[6].Trim().ToLowerInvariant()); stype = stypes?.GetScenarioType(sthash) ?? defaulttype; } if (vals.Length > 7) { var mshash = JenkHash.GenHash(vals[7].Trim().ToLowerInvariant()); modelset = stypes?.GetPedModelSet(mshash) ?? null; if (modelset == null) modelset = stypes?.GetVehicleModelSet(mshash) ?? null; } if (vals.Length > 8) { if (!uint.TryParse(vals[8].Trim(), out flags)) flags = defaultflags; } if (!ok) continue; thisnode = rgn.AddNode(); thisnode.MyPoint.Direction = dir; thisnode.MyPoint.Type = stype; thisnode.MyPoint.ModelSet = modelset; thisnode.MyPoint.Flags = (Unk_700327466)flags; thisnode.ChainingNode = new MCScenarioChainingNode(); thisnode.ChainingNode.ScenarioNode = thisnode; thisnode.ChainingNode.Chain = chain; thisnode.ChainingNode.Type = stype; thisnode.ChainingNode.TypeHash = stype?.NameHash ?? 0; thisnode.ChainingNode.NotLast = (i < (lines.Length - 1)); thisnode.ChainingNode.NotFirst = (lastnode != null); thisnode.SetPosition(pos); thisnode.Orientation = thisnode.MyPoint.Orientation; paths.AddNode(thisnode.ChainingNode); if (lastnode != null) { var edge = new MCScenarioChainingEdge(); edge.NodeFrom = lastnode.ChainingNode; edge.NodeTo = thisnode.ChainingNode; edge.NodeIndexFrom = (ushort)lastnode.ChainingNode.NodeIndex; edge.NodeIndexTo = (ushort)thisnode.ChainingNode.NodeIndex; edge.Action = action; edge.NavMode = navMode; edge.NavSpeed = navSpeed; paths.AddEdge(edge); chain.AddEdge(edge); lastedge = edge; } lastnode = thisnode; } LoadProjectTree(); if (lastnode != null) { TrySelectScenarioNodeTreeNode(lastnode); CurrentScenarioNode = lastnode; } CurrentScenarioChainEdge = lastedge; LoadScenarioChainTabPage(); //LoadScenarioTabPage(); //LoadScenarioNodeTabPages(); if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } else { CurrentScenario.ScenarioRegion.BuildBVH(); CurrentScenario.ScenarioRegion.BuildVertices(); //for the graphics... } } private void ImportMenyooXml() { if (CurrentProjectFile == null) { NewProject(); } var xmlpath = ShowOpenDialog("XML Files|*.xml", string.Empty); if (string.IsNullOrEmpty(xmlpath)) return; var xmlstr = string.Empty; try { xmlstr = File.ReadAllText(xmlpath); } catch (Exception ex) { MessageBox.Show("Error loading file!\n" + ex.ToString()); } if (string.IsNullOrEmpty(xmlstr)) return; var finf = new FileInfo(xmlpath); MenyooXml menyooXml = new MenyooXml(); menyooXml.FilePath = xmlpath; menyooXml.FileName = finf.Name; menyooXml.Name = Path.GetFileNameWithoutExtension(finf.Name); menyooXml.Init(xmlstr); string fname = menyooXml.Name + ".ymap"; lock (ymapsyncroot) { YmapFile ymap = CurrentProjectFile.AddYmapFile(fname); if (ymap != null) { ymap.Loaded = true; ymap.HasChanged = true; //new ymap, flag as not saved ymap._CMapData.contentFlags = 65; //stream flags value } CurrentYmapFile = ymap; } CurrentProjectFile.HasChanged = true; int pedcount = 0; int carcount = 0; int entcount = 0; int unkcount = 0; foreach (var placement in menyooXml.Placements) { if (placement.Type == 1) { pedcount++; } else if (placement.Type == 2) { CCarGen ccg = new CCarGen(); var rotq = Quaternion.Invert(new Quaternion(placement.Rotation)); Vector3 cdir = rotq.Multiply(new Vector3(0, 5, 0)); ccg.flags = 3680; ccg.orientX = cdir.X; ccg.orientY = cdir.Y; ccg.perpendicularLength = 2.6f; ccg.position = placement.Position; ccg.carModel = placement.ModelHash; YmapCarGen cg = new YmapCarGen(CurrentYmapFile, ccg); if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { CurrentYmapFile.AddCarGen(cg); } } else { CurrentYmapFile.AddCarGen(cg); } carcount++; } else if (placement.Type == 3) //standard entity { CEntityDef cent = new CEntityDef(); cent.archetypeName = placement.ModelHash; cent.position = placement.Position; cent.rotation = placement.Rotation; cent.scaleXY = 1.0f; cent.scaleZ = 1.0f; cent.flags = placement.Dynamic ? 32u : 0;// 1572872; //? cent.parentIndex = -1; cent.lodDist = placement.LodDistance; cent.lodLevel = Unk_1264241711.LODTYPES_DEPTH_ORPHANHD; cent.priorityLevel = Unk_648413703.PRI_REQUIRED; cent.ambientOcclusionMultiplier = 255; cent.artificialAmbientOcclusion = 255; YmapEntityDef ent = new YmapEntityDef(CurrentYmapFile, 0, ref cent); ent.SetArchetype(GameFileCache.GetArchetype(cent.archetypeName)); if (WorldForm != null) { lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering... { CurrentYmapFile.AddEntity(ent); } } else { CurrentYmapFile.AddEntity(ent); } entcount++; } else { unkcount++; } } LoadProjectTree(); CalcYmapFlags(); CalcYmapExtents(); MessageBox.Show(entcount.ToString() + " entities imported. \n" + carcount.ToString() + " car generators imported. \n" + pedcount.ToString() + " peds ignored. \n" + unkcount.ToString() + " others ignored."); } public void GetVisibleYmaps(Camera camera, Dictionary ymaps) { if (hidegtavmap) { ymaps.Clear(); //remove all the gtav ymaps. } if (renderentities && (CurrentProjectFile != null)) { lock (ymapsyncroot) { for (int i = 0; i < CurrentProjectFile.YmapFiles.Count; i++) { var ymap = CurrentProjectFile.YmapFiles[i]; if (ymap.Loaded) { ymaps[ymap._CMapData.name] = ymap; } } } } } public void GetVisibleCollisionMeshes(Camera camera, List items) { //eventually will need to change this to use a list of Ybn's... if (hidegtavmap) { items.Clear(); } } public void GetVisibleWaterQuads(Camera camera, List quads) { if (hidegtavmap) { quads.Clear(); } } public void GetVisibleYnds(Camera camera, List ynds) { if (hidegtavmap) { ynds.Clear(); } if (CurrentProjectFile == null) return; lock (yndsyncroot) { visibleynds.Clear(); for (int i = 0; i < ynds.Count; i++) { var ynd = ynds[i]; visibleynds[ynd.AreaID] = ynd; } for (int i = 0; i < CurrentProjectFile.YndFiles.Count; i++) { var ynd = CurrentProjectFile.YndFiles[i]; if (ynd.Loaded) { visibleynds[ynd.AreaID] = ynd; } } ynds.Clear(); foreach (var ynd in visibleynds.Values) { ynds.Add(ynd); } } } public void GetVisibleYnvs(Camera camera, List ynvs) { if (hidegtavmap) { ynvs.Clear(); } if (CurrentProjectFile == null) return; lock (ynvsyncroot) { visibleynvs.Clear(); for (int i = 0; i < ynvs.Count; i++) { var ynv = ynvs[i]; visibleynvs[ynv.AreaID] = ynv; } for (int i = 0; i < CurrentProjectFile.YnvFiles.Count; i++) { var ynv = CurrentProjectFile.YnvFiles[i]; if (ynv.Loaded) { visibleynvs[ynv.AreaID] = ynv; } } ynvs.Clear(); foreach (var ynv in visibleynvs.Values) { ynvs.Add(ynv); } } } public void GetVisibleTrainTracks(Camera camera, List tracks) { if (hidegtavmap) { tracks.Clear(); } if (CurrentProjectFile == null) return; lock (trainsyncroot) { visibletrains.Clear(); for (int i = 0; i < tracks.Count; i++) { var track = tracks[i]; visibletrains[track.Name] = track; } for (int i = 0; i < CurrentProjectFile.TrainsFiles.Count; i++) { var track = CurrentProjectFile.TrainsFiles[i]; if (track.Loaded) { visibletrains[track.Name] = track; } } tracks.Clear(); foreach (var track in visibletrains.Values) { tracks.Add(track); } } } public void GetVisibleScenarios(Camera camera, List ymts) { if (hidegtavmap) { ymts.Clear(); } if (CurrentProjectFile == null) return; lock (scenariosyncroot) { visiblescenarios.Clear(); for (int i = 0; i < ymts.Count; i++) { var ymt = ymts[i]; visiblescenarios[ymt.Name] = ymt; } for (int i = 0; i < CurrentProjectFile.ScenarioFiles.Count; i++) { var scenario = CurrentProjectFile.ScenarioFiles[i]; if (scenario.Loaded) { visiblescenarios[scenario.Name] = scenario; } } ymts.Clear(); foreach (var ymt in visiblescenarios.Values) { ymts.Add(ymt); } } } public void OnWorldSelectionChanged(MapSelection sel) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldSelectionChanged(sel); })); } else { var ent = sel.EntityDef; var cargen = sel.CarGenerator; var pathnode = sel.PathNode; var pathlink = sel.PathLink; var navpoly = sel.NavPoly; var trainnode = sel.TrainTrackNode; var scenariond = sel.ScenarioNode; YmapFile ymap = ent?.Ymap; YndFile ynd = pathnode?.Ynd; YnvFile ynv = navpoly?.Ynv; TrainTrack traintrack = trainnode?.Track; YmtFile scenario = scenariond?.Ymt; if (cargen != null) { ymap = cargen.Ymap; } if (YmapExistsInProject(ymap)) { if (ent != CurrentEntity) { TrySelectEntityTreeNode(ent); } if (cargen != CurrentCarGen) { TrySelectCarGenTreeNode(cargen); } } else if (YndExistsInProject(ynd)) { if (pathnode != CurrentPathNode) { TrySelectPathNodeTreeNode(pathnode); } } else if (YnvExistsInProject(ynv)) { if (navpoly != CurrentNavPoly) { TrySelectNavPolyTreeNode(navpoly); } } else if (TrainTrackExistsInProject(traintrack)) { if (trainnode != CurrentTrainNode) { TrySelectTrainNodeTreeNode(trainnode); } } else if (ScenarioExistsInProject(scenario)) { if ((scenariond != null) && (scenariond != CurrentScenarioNode)) { TrySelectScenarioNodeTreeNode(scenariond); } } else { ProjectTreeView.SelectedNode = null; if (ymap != null) { MainTabControl.SelectedTab = YmapTabPage; } else if (ynd != null) { MainTabControl.SelectedTab = YndTabPage; } else if (ynv != null) { MainTabControl.SelectedTab = YnvTabPage; } else if (traintrack != null) { MainTabControl.SelectedTab = TrainsTabPage; } else if (scenario != null) { MainTabControl.SelectedTab = ScenarioTabPage; } if (ent != null) { YmapTabControl.SelectedTab = YmapEntityTabPage; } else if (cargen != null) { YmapTabControl.SelectedTab = YmapCarGenTabPage; } if (pathnode != null) { YndTabControl.SelectedTab = YndNodeTabPage; } if (trainnode != null) { TrainsTabControl.SelectedTab = TrainNodeTabPage; } if (scenariond != null) { SelectScenarioNodeTabPages(scenariond); } } CurrentYmapFile = ymap; CurrentEntity = ent; CurrentCarGen = cargen; CurrentYndFile = ynd; CurrentPathNode = pathnode; CurrentPathLink = pathlink; CurrentYnvFile = ynv; CurrentNavPoly = navpoly; CurrentTrainTrack = traintrack; CurrentTrainNode = trainnode; CurrentScenario = scenario; CurrentScenarioNode = scenariond; RefreshUI(); } } catch { } } public void OnWorldSelectionModified(MapSelection sel, List items) { if (sel.MultipleSelection) { } else if (sel.EntityDef != null) { OnWorldEntityModified(sel.EntityDef); } else if (sel.CarGenerator != null) { OnWorldCarGenModified(sel.CarGenerator); } else if (sel.PathNode != null) { OnWorldPathNodeModified(sel.PathNode, sel.PathLink); } else if (sel.NavPoly != null) { OnWorldNavPolyModified(sel.NavPoly); } else if (sel.TrainTrackNode != null) { OnWorldTrainNodeModified(sel.TrainTrackNode); } else if (sel.ScenarioNode != null) { OnWorldScenarioNodeModified(sel.ScenarioNode); } } private void OnWorldEntityModified(YmapEntityDef ent) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldEntityModified(ent); })); } else { if ((ent.Ymap == null) || (ent.MloParent != null)) { return;//TODO: properly handle interior entities! } if (CurrentProjectFile == null) { NewProject(); } if (!YmapExistsInProject(ent.Ymap)) { ent.Ymap.HasChanged = true; AddYmapToProject(ent.Ymap); TrySelectEntityTreeNode(ent); } if (ent != CurrentEntity) { CurrentEntity = ent; TrySelectEntityTreeNode(ent); } if (ent == CurrentEntity) { LoadEntityTabPage(); if (ent.Ymap != null) { SetYmapHasChanged(true); } } } } catch { } } private void OnWorldCarGenModified(YmapCarGen cargen) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldCarGenModified(cargen); })); } else { if (cargen?.Ymap == null) return; if (CurrentProjectFile == null) { NewProject(); } if (!YmapExistsInProject(cargen.Ymap)) { cargen.Ymap.HasChanged = true; AddYmapToProject(cargen.Ymap); TrySelectCarGenTreeNode(cargen); } if (cargen != CurrentCarGen) { CurrentCarGen = cargen; TrySelectCarGenTreeNode(cargen); } if (cargen == CurrentCarGen) { LoadCarGenTabPage(); UpdateCarGenTreeNode(cargen); if (cargen.Ymap != null) { SetYmapHasChanged(true); } } } } catch { } } private void OnWorldPathNodeModified(YndNode node, YndLink link) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldPathNodeModified(node, link); })); } else { if (node?.Ynd == null) return; if (CurrentProjectFile == null) { NewProject(); } if (!YndExistsInProject(node.Ynd)) { node.Ynd.HasChanged = true; AddYndToProject(node.Ynd); TrySelectPathNodeTreeNode(node); } if (node != CurrentPathNode) { CurrentPathNode = node; TrySelectPathNodeTreeNode(node); } //if (link != CurrentPathLink) //{ // CurrentPathLink = link; // LoadPathNodeLinkPage(); //} if (node == CurrentPathNode) { //LoadYndTabPage(); LoadPathNodeTabPage(); //UpdatePathNodeTreeNode(node); if (node.Ynd != null) { SetYndHasChanged(true); } } } } catch { } } private void OnWorldNavPolyModified(YnvPoly poly) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldNavPolyModified(poly); })); } else { if (poly?.Ynv == null) return; if (CurrentProjectFile == null) { NewProject(); } if (!YnvExistsInProject(poly.Ynv)) { poly.Ynv.HasChanged = true; AddYnvToProject(poly.Ynv); TrySelectNavPolyTreeNode(poly); } if (poly != CurrentNavPoly) { CurrentNavPoly = poly; TrySelectNavPolyTreeNode(poly); } if (poly == CurrentNavPoly) { LoadYnvTabPage(); //UpdateNavPolyTreeNode(poly); if (poly.Ynv != null) { SetYnvHasChanged(true); } } } } catch { } } private void OnWorldTrainNodeModified(TrainTrackNode node) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldTrainNodeModified(node); })); } else { if (node?.Track == null) return; if (CurrentProjectFile == null) { NewProject(); } if (!TrainTrackExistsInProject(node.Track)) { node.Track.HasChanged = true; AddTrainTrackToProject(node.Track); TrySelectTrainNodeTreeNode(node); } if (node != CurrentTrainNode) { CurrentTrainNode = node; TrySelectTrainNodeTreeNode(node); } if (node == CurrentTrainNode) { LoadTrainNodeTabPage(); if (node.Track != null) { SetTrainTrackHasChanged(true); } } } } catch { } } private void OnWorldScenarioNodeModified(ScenarioNode node) { try { if (InvokeRequired) { BeginInvoke(new Action(() => { OnWorldScenarioNodeModified(node); })); } else { if (node?.Ymt == null) return; if (CurrentProjectFile == null) { NewProject(); } if (!ScenarioExistsInProject(node.Ymt)) { node.Ymt.HasChanged = true; AddScenarioToProject(node.Ymt); TrySelectScenarioNodeTreeNode(node); } if (node != CurrentScenarioNode) { CurrentScenarioNode = node; TrySelectScenarioNodeTreeNode(node); } if (node == CurrentScenarioNode) { LoadScenarioTabPage(); LoadScenarioNodeTabPages(); if (node?.Ymt != null) { SetScenarioHasChanged(true); } } } } catch { } } private bool IsBitSet(uint value, int bit) { return (((value >> bit) & 1) > 0); } private uint SetBit(uint value, int bit) { return (value | (1u << bit)); } private uint ClearBit(uint value, int bit) { return (value & (~(1u << bit))); } private uint UpdateBit(uint value, int bit, bool flag) { if (flag) return SetBit(value, bit); else return ClearBit(value, bit); } private string ShowOpenDialog(string filter, string filename) { OpenFileDialog.FileName = filename; OpenFileDialog.Filter = filter; OpenFileDialog.Multiselect = false; if (OpenFileDialog.ShowDialog(this) != DialogResult.OK) { return string.Empty; } return OpenFileDialog.FileName; } private string[] ShowOpenDialogMulti(string filter, string filename) { OpenFileDialog.FileName = filename; OpenFileDialog.Filter = filter; OpenFileDialog.Multiselect = true; if (OpenFileDialog.ShowDialog(this) != DialogResult.OK) { return null; } return OpenFileDialog.FileNames; } private string ShowSaveDialog(string filter, string filename) { SaveFileDialog.FileName = filename; SaveFileDialog.Filter = filter; if (SaveFileDialog.ShowDialog(this) != DialogResult.OK) { return string.Empty; } return SaveFileDialog.FileName; } private RpfFileEntry FindParentYmapEntry(uint hash) { if (CurrentProjectFile != null) { foreach (var ymap in CurrentProjectFile.YmapFiles) { if ((ymap._CMapData.name.Hash == hash) || (JenkHash.GenHash(Path.GetFileNameWithoutExtension(ymap.Name)) == hash)) { return ymap.RpfFileEntry; } } } if ((GameFileCache != null) && (GameFileCache.IsInited)) { return GameFileCache.GetYmapEntry(hash); } return null; } private bool YmapExistsInProject(YmapFile ymap) { if (ymap == null) return false; if (CurrentProjectFile == null) return false; return CurrentProjectFile.ContainsYmap(ymap); } private bool YndExistsInProject(YndFile ynd) { if (ynd == null) return false; if (CurrentProjectFile == null) return false; return CurrentProjectFile.ContainsYnd(ynd); } private bool YnvExistsInProject(YnvFile ynv) { if (ynv == null) return false; if (CurrentProjectFile == null) return false; return CurrentProjectFile.ContainsYnv(ynv); } private bool TrainTrackExistsInProject(TrainTrack track) { if (track == null) return false; if (CurrentProjectFile == null) return false; return CurrentProjectFile.ContainsTrainTrack(track); } private bool ScenarioExistsInProject(YmtFile ymt) { if (ymt == null) return false; if (CurrentProjectFile == null) return false; return CurrentProjectFile.ContainsScenario(ymt); } private TreeNode GetChildTreeNode(TreeNode node, string name) { if (node == null) return null; var nodes = node.Nodes.Find(name, false); if ((nodes == null) || (nodes.Length != 1)) return null; return nodes[0]; } private TreeNode FindYmapTreeNode(YmapFile ymap) { if (ProjectTreeView.Nodes.Count <= 0) return null; var projnode = ProjectTreeView.Nodes[0]; var ymapsnode = GetChildTreeNode(projnode, "Ymap"); if (ymapsnode == null) return null; for (int i = 0; i < ymapsnode.Nodes.Count; i++) { var ymapnode = ymapsnode.Nodes[i]; if (ymapnode.Tag == ymap) return ymapnode; } return null; } private TreeNode FindEntityTreeNode(YmapEntityDef ent) { if (ent == null) return null; TreeNode ymapnode = FindYmapTreeNode(ent.Ymap); if (ymapnode == null) return null; var entsnode = GetChildTreeNode(ymapnode, "Entities"); if (entsnode == null) return null; for (int i = 0; i < entsnode.Nodes.Count; i++) { TreeNode entnode = entsnode.Nodes[i]; if (entnode.Tag == ent) return entnode; } return null; } private TreeNode FindCarGenTreeNode(YmapCarGen cargen) { if (cargen == null) return null; TreeNode ymapnode = FindYmapTreeNode(cargen.Ymap); if (ymapnode == null) return null; var cargensnode = GetChildTreeNode(ymapnode, "CarGens"); if (cargensnode == null) return null; for (int i = 0; i < cargensnode.Nodes.Count; i++) { TreeNode cargennode = cargensnode.Nodes[i]; if (cargennode.Tag == cargen) return cargennode; } return null; } private TreeNode FindYndTreeNode(YndFile ynd) { if (ProjectTreeView.Nodes.Count <= 0) return null; var projnode = ProjectTreeView.Nodes[0]; var yndsnode = GetChildTreeNode(projnode, "Ynd"); if (yndsnode == null) return null; for (int i = 0; i < yndsnode.Nodes.Count; i++) { var yndnode = yndsnode.Nodes[i]; if (yndnode.Tag == ynd) return yndnode; } return null; } private TreeNode FindPathNodeTreeNode(YndNode n) { if (n == null) return null; TreeNode yndnode = FindYndTreeNode(n.Ynd); var nodesnode = GetChildTreeNode(yndnode, "Nodes"); if (nodesnode == null) return null; for (int i = 0; i < nodesnode.Nodes.Count; i++) { TreeNode nnode = nodesnode.Nodes[i]; if (nnode.Tag == n) return nnode; } return null; } private TreeNode FindYnvTreeNode(YnvFile ynv) { if (ProjectTreeView.Nodes.Count <= 0) return null; var projnode = ProjectTreeView.Nodes[0]; var ynvsnode = GetChildTreeNode(projnode, "Ynv"); if (ynvsnode == null) return null; for (int i = 0; i < ynvsnode.Nodes.Count; i++) { var yndnode = ynvsnode.Nodes[i]; if (yndnode.Tag == ynv) return yndnode; } return null; } private TreeNode FindNavPolyTreeNode(YnvPoly p) { if (p == null) return null; TreeNode ynvnode = FindYnvTreeNode(p.Ynv); var polysnode = GetChildTreeNode(ynvnode, "Polygons"); if (polysnode == null) return null; for (int i = 0; i < polysnode.Nodes.Count; i++) { TreeNode pnode = polysnode.Nodes[i]; if (pnode.Tag == p) return pnode; } return null; } private TreeNode FindTrainTrackTreeNode(TrainTrack track) { if (ProjectTreeView.Nodes.Count <= 0) return null; var projnode = ProjectTreeView.Nodes[0]; var trainsnode = GetChildTreeNode(projnode, "Trains"); if (trainsnode == null) return null; for (int i = 0; i < trainsnode.Nodes.Count; i++) { var trainnode = trainsnode.Nodes[i]; if (trainnode.Tag == track) return trainnode; } return null; } private TreeNode FindTrainNodeTreeNode(TrainTrackNode n) { if (n == null) return null; TreeNode tracknode = FindTrainTrackTreeNode(n.Track); var nodesnode = GetChildTreeNode(tracknode, "Nodes"); if (nodesnode == null) return null; for (int i = 0; i < nodesnode.Nodes.Count; i++) { TreeNode nnode = nodesnode.Nodes[i]; if (nnode.Tag == n) return nnode; } return null; } private TreeNode FindScenarioTreeNode(YmtFile ymt) { if (ProjectTreeView.Nodes.Count <= 0) return null; var projnode = ProjectTreeView.Nodes[0]; var scenariosnode = GetChildTreeNode(projnode, "Scenarios"); if (scenariosnode == null) return null; for (int i = 0; i < scenariosnode.Nodes.Count; i++) { var ymtnode = scenariosnode.Nodes[i]; if (ymtnode.Tag == ymt) return ymtnode; } return null; } private TreeNode FindScenarioNodeTreeNode(ScenarioNode p) { if (p == null) return null; TreeNode ymtnode = FindScenarioTreeNode(p.Ymt); var pointsnode = GetChildTreeNode(ymtnode, "Points"); if (pointsnode == null) return null; for (int i = 0; i < pointsnode.Nodes.Count; i++) { TreeNode pnode = pointsnode.Nodes[i]; if (pnode.Tag == p) return pnode; } return null; } private void TrySelectEntityTreeNode(YmapEntityDef ent) { TreeNode entnode = FindEntityTreeNode(ent); if (entnode != null) { ProjectTreeView.SelectedNode = entnode; } } private void TrySelectCarGenTreeNode(YmapCarGen cargen) { TreeNode cargennode = FindCarGenTreeNode(cargen); if (cargennode != null) { ProjectTreeView.SelectedNode = cargennode; } } private void UpdateCarGenTreeNode(YmapCarGen cargen) { var tn = FindCarGenTreeNode(cargen); if (tn != null) { tn.Text = cargen.ToString(); } } private void TrySelectPathNodeTreeNode(YndNode node) { TreeNode tnode = FindPathNodeTreeNode(node); if (tnode == null) { tnode = FindYndTreeNode(node?.Ynd); } if (tnode != null) { ProjectTreeView.SelectedNode = tnode; } } private void UpdatePathNodeTreeNode(YndNode node) { var tn = FindPathNodeTreeNode(node); if (tn != null) { tn.Text = node._RawData.ToString(); } } private void TrySelectNavPolyTreeNode(YnvPoly poly) { TreeNode tnode = FindNavPolyTreeNode(poly); if (tnode == null) { tnode = FindYnvTreeNode(poly?.Ynv); } if (tnode != null) { ProjectTreeView.SelectedNode = tnode; } } private void UpdateNavPolyTreeNode(YnvPoly poly) { var tn = FindNavPolyTreeNode(poly); if (tn != null) { tn.Text = poly._RawData.ToString(); } } private void TrySelectTrainNodeTreeNode(TrainTrackNode node) { TreeNode tnode = FindTrainNodeTreeNode(node); if (tnode == null) { tnode = FindTrainTrackTreeNode(node?.Track); } if (tnode != null) { ProjectTreeView.SelectedNode = tnode; } } private void UpdateTrainNodeTreeNode(TrainTrackNode node) { var tn = FindTrainNodeTreeNode(node); if (tn != null) { tn.Text = node.ToString(); } } private void TrySelectScenarioTreeNode(YmtFile scenario) { TreeNode tnode = FindScenarioTreeNode(scenario); if (tnode != null) { ProjectTreeView.SelectedNode = tnode; } } private void TrySelectScenarioNodeTreeNode(ScenarioNode node) { TreeNode tnode = FindScenarioNodeTreeNode(node); if (tnode == null) { tnode = FindScenarioTreeNode(node?.Ymt); } if (tnode != null) { ProjectTreeView.SelectedNode = tnode; } } private void UpdateScenarioNodeTreeNode(ScenarioNode node) { var tn = FindScenarioNodeTreeNode(node); if (tn != null) { tn.Text = node.MedTypeName + ": " + node.StringText; } } private void ProjectForm_FormClosing(object sender, FormClosingEventArgs e) { CloseProject(); } private void ProjectForm_FormClosed(object sender, FormClosedEventArgs e) { if (WorldForm != null) { WorldForm.OnProjectFormClosed(); } } private void FileNewProjectMenu_Click(object sender, EventArgs e) { NewProject(); } private void FileNewYmapMenu_Click(object sender, EventArgs e) { NewYmap(); } private void FileNewYndMenu_Click(object sender, EventArgs e) { NewYnd(); } private void FileNewYnvMenu_Click(object sender, EventArgs e) { NewYnv(); } private void FileNewTrainsMenu_Click(object sender, EventArgs e) { NewTrainTrack(); } private void FileNewScenarioMenu_Click(object sender, EventArgs e) { NewScenario(); } private void FileOpenProjectMenu_Click(object sender, EventArgs e) { if (CurrentProjectFile != null) { ////unload current project first? //if (MessageBox.Show("Close the current project and open an existing one?", "Confirm close project", MessageBoxButtons.YesNo) != DialogResult.Yes) //{ // return; //} CloseProject(); } OpenProject(); } private void FileOpenYmapMenu_Click(object sender, EventArgs e) { OpenYmap(); } private void FileOpenYndMenu_Click(object sender, EventArgs e) { OpenYnd(); } private void FileOpenYnvMenu_Click(object sender, EventArgs e) { OpenYnv(); } private void FileOpenTrainsMenu_Click(object sender, EventArgs e) { OpenTrainTrack(); } private void FileOpenScenarioMenu_Click(object sender, EventArgs e) { OpenScenario(); } private void FileCloseProjectMenu_Click(object sender, EventArgs e) { CloseProject(); } private void FileSaveProjectMenu_Click(object sender, EventArgs e) { SaveProject(false); } private void FileSaveProjectAsMenu_Click(object sender, EventArgs e) { SaveProject(true); } private void FileSaveItemMenu_Click(object sender, EventArgs e) { SaveCurrentItem(false); } private void FileSaveItemAsMenu_Click(object sender, EventArgs e) { SaveCurrentItem(true); } private void YmapNewEntityMenu_Click(object sender, EventArgs e) { NewEntity(); } private void YmapNewCarGenMenu_Click(object sender, EventArgs e) { NewCarGen(); } private void YmapAddToProjectMenu_Click(object sender, EventArgs e) { AddYmapToProject(CurrentYmapFile); } private void YmapRemoveFromProjectMenu_Click(object sender, EventArgs e) { RemoveYmapFromProject(); } private void YndNewNodeMenu_Click(object sender, EventArgs e) { NewPathNode(); } private void YndAddToProjectMenu_Click(object sender, EventArgs e) { AddYndToProject(CurrentYndFile); } private void YndRemoveFromProjectMenu_Click(object sender, EventArgs e) { RemoveYndFromProject(); } private void YnvNewPolygonMenu_Click(object sender, EventArgs e) { NewNavPoly(); } private void YnvAddToProjectMenu_Click(object sender, EventArgs e) { //AddYnvToProject(CurrentYnvFile); } private void YnvRemoveFromProjectMenu_Click(object sender, EventArgs e) { RemoveYnvFromProject(); } private void TrainsNewNodeMenu_Click(object sender, EventArgs e) { NewTrainNode(); } private void TrainsAddToProjectMenu_Click(object sender, EventArgs e) { AddTrainTrackToProject(CurrentTrainTrack); } private void TrainsRemoveFromProjectMenu_Click(object sender, EventArgs e) { RemoveTrainTrackFromProject(); } private void ScenarioNewPointMenu_Click(object sender, EventArgs e) { CurrentScenarioNode = null; NewScenarioNode(); } private void ScenarioNewPointFromSelectedMenu_Click(object sender, EventArgs e) { NewScenarioNode(); } private void ScenarioNewEntityOverrideMenu_Click(object sender, EventArgs e) { AddScenarioEntity(); } private void ScenarioNewChainMenu_Click(object sender, EventArgs e) { AddScenarioChain(); } private void ScenarioNewClusterMenu_Click(object sender, EventArgs e) { AddScenarioCluster(); } private void ScenarioImportChainMenu_Click(object sender, EventArgs e) { ImportScenarioChain(); } private void ScenarioAddToProjectMenu_Click(object sender, EventArgs e) { AddScenarioToProject(CurrentScenario); } private void ScenarioRemoveFromProjectMenu_Click(object sender, EventArgs e) { RemoveScenarioFromProject(); } private void ToolsImportMenyooXmlMenu_Click(object sender, EventArgs e) { ImportMenyooXml(); } private void OptionsHideGTAVMapMenu_Click(object sender, EventArgs e) { ProjectHideMapCheckBox.Checked = !hidegtavmap; } private void ProjectNameTextBox_TextChanged(object sender, EventArgs e) { if (CurrentProjectFile != null) { if (CurrentProjectFile.Name != ProjectNameTextBox.Text) { CurrentProjectFile.Name = ProjectNameTextBox.Text; SetProjectHasChanged(true); } } } private void ProjectTreeView_AfterSelect(object sender, TreeViewEventArgs e) { YmapFile ymap = null; YmapEntityDef yent = null; YmapCarGen ycgen = null; YndFile ynd = null; YndNode ynode = null; YnvFile ynv = null; YnvPoly ypoly = null; TrainTrack tt = null; TrainTrackNode ttnode = null; YmtFile scenario = null; ScenarioNode scenarionode = null; object tag = null; var node = ProjectTreeView.SelectedNode; if (node != null) { tag = node.Tag; ymap = tag as YmapFile; yent = tag as YmapEntityDef; ycgen = tag as YmapCarGen; ynd = tag as YndFile; ynode = tag as YndNode; ynv = tag as YnvFile; ypoly = tag as YnvPoly; tt = tag as TrainTrack; ttnode = tag as TrainTrackNode; scenario = tag as YmtFile; if ((scenario != null) && (scenario.ScenarioRegion == null)) scenario = null;//incase other types of ymt files make it into the project... scenarionode = tag as ScenarioNode; } CurrentYmapFile = ymap; CurrentEntity = yent; CurrentCarGen = ycgen; CurrentYndFile = ynd; CurrentPathNode = ynode; CurrentYnvFile = ynv; CurrentNavPoly = ypoly; CurrentTrainTrack = tt; CurrentTrainNode = ttnode; CurrentScenario = scenario; CurrentScenarioNode = scenarionode; if (tag == CurrentProjectFile) { MainTabControl.SelectedTab = ProjectTabPage; } if (yent != null) { CurrentYmapFile = yent.Ymap; MainTabControl.SelectedTab = YmapTabPage; YmapTabControl.SelectedTab = YmapEntityTabPage; } else if (ycgen != null) { CurrentYmapFile = ycgen.Ymap; MainTabControl.SelectedTab = YmapTabPage; YmapTabControl.SelectedTab = YmapCarGenTabPage; } else if (ymap != null) { CurrentYmapFile = ymap; MainTabControl.SelectedTab = YmapTabPage; YmapTabControl.SelectedTab = YmapYmapTabPage; } if (ynode != null) { CurrentYndFile = ynode.Ynd; MainTabControl.SelectedTab = YndTabPage; YndTabControl.SelectedTab = YndNodeTabPage; } else if (ynd != null) { MainTabControl.SelectedTab = YndTabPage; YndTabControl.SelectedTab = YndYndTabPage; } if (ypoly != null) { CurrentYnvFile = ypoly.Ynv; MainTabControl.SelectedTab = YnvTabPage; YnvTabControl.SelectedTab = YnvPolyTabPage; } else if (ynv != null) { MainTabControl.SelectedTab = YnvTabPage; YnvTabControl.SelectedTab = YnvYnvTabPage; } if (ttnode != null) { CurrentTrainTrack = ttnode.Track; MainTabControl.SelectedTab = TrainsTabPage; TrainsTabControl.SelectedTab = TrainNodeTabPage; } else if (tt != null) { MainTabControl.SelectedTab = TrainsTabPage; TrainsTabControl.SelectedTab = TrainTrackTabPage; } if (scenarionode != null) { CurrentScenario = scenarionode.Ymt; MainTabControl.SelectedTab = ScenarioTabPage; SelectScenarioNodeTabPages(scenarionode); } else if (scenario != null) { MainTabControl.SelectedTab = ScenarioTabPage; ScenarioTabControl.SelectedTab = ScenarioYmtTabPage; } RefreshUI(); } private void ProjectShowEntitiesCheckBox_CheckedChanged(object sender, EventArgs e) { renderentities = ProjectShowEntitiesCheckBox.Checked; } private void ProjectHideMapCheckBox_CheckedChanged(object sender, EventArgs e) { hidegtavmap = ProjectHideMapCheckBox.Checked; OptionsHideGTAVMapMenu.Checked = hidegtavmap; } private void ProjectManifestGenerateButton_Click(object sender, EventArgs e) { GenerateProjectManifest(); } private void YmapNameTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; uint hash = 0; string name = YmapNameTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } YmapNameHashLabel.Text = "Hash: " + hash.ToString(); if (CurrentYmapFile != null) { lock (ymapsyncroot) { string ymname = name + ".ymap"; if (CurrentYmapFile.Name != ymname) { CurrentYmapFile.Name = ymname; CurrentYmapFile._CMapData.name = new MetaHash(hash); SetYmapHasChanged(true); } } } } private void YmapParentTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; uint hash = 0; string name = YmapParentTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } YmapParentHashLabel.Text = "Hash: " + hash.ToString(); if (hash != 0) { var entry = FindParentYmapEntry(hash); if (entry == null) { YmapParentHashLabel.Text += " (not found!)"; } } if (CurrentYmapFile != null) { lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.parent.Hash != hash) { CurrentYmapFile._CMapData.parent = new MetaHash(hash); SetYmapHasChanged(true); //TODO: confirm entity parent linkage? } } } } private void YmapFlagsTextBox_TextChanged(object sender, EventArgs e) { SetYmapFlagsFromTextBoxes(); } private void YmapContentFlagsTextBox_TextChanged(object sender, EventArgs e) { SetYmapFlagsFromTextBoxes(); } private void YmapCFlagsHDCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsLODCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsSLOD2CheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsInteriorCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsSLODCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsOcclusionCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsPhysicsCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsLODLightsCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsDistLightsCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsCriticalCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCFlagsGrassCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapFlagsScriptedCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapFlagsLODCheckBox_CheckedChanged(object sender, EventArgs e) { SetYmapFlagsFromCheckBoxes(); } private void YmapCalculateFlagsButton_Click(object sender, EventArgs e) { CalcYmapFlags(); } private void YmapEntitiesExtentsMinTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentYmapFile == null) return; Vector3 v = FloatUtil.ParseVector3String(YmapEntitiesExtentsMinTextBox.Text); lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.entitiesExtentsMin != v) { CurrentYmapFile._CMapData.entitiesExtentsMin = v; SetYmapHasChanged(true); } } } private void YmapEntitiesExtentsMaxTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentYmapFile == null) return; Vector3 v = FloatUtil.ParseVector3String(YmapEntitiesExtentsMaxTextBox.Text); lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.entitiesExtentsMax != v) { CurrentYmapFile._CMapData.entitiesExtentsMax = v; SetYmapHasChanged(true); } } } private void YmapStreamingExtentsMinTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentYmapFile == null) return; Vector3 v = FloatUtil.ParseVector3String(YmapStreamingExtentsMinTextBox.Text); lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.streamingExtentsMin != v) { CurrentYmapFile._CMapData.streamingExtentsMin = v; SetYmapHasChanged(true); } } } private void YmapStreamingExtentsMaxTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentYmapFile == null) return; Vector3 v = FloatUtil.ParseVector3String(YmapStreamingExtentsMaxTextBox.Text); lock (ymapsyncroot) { if (CurrentYmapFile._CMapData.streamingExtentsMax != v) { CurrentYmapFile._CMapData.streamingExtentsMax = v; SetYmapHasChanged(true); } } } private void YmapCalculateExtentsButton_Click(object sender, EventArgs e) { CalcYmapExtents(); } private void YmapPhysicsDictionariesTextBox_TextChanged(object sender, EventArgs e) { SetYmapPhysicsDictionariesFromTextbox(); } private void EntityArchetypeTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; uint hash = 0; string name = EntityArchetypeTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } EntityArchetypeHashLabel.Text = "Hash: " + hash.ToString(); var arch = GameFileCache.GetArchetype(hash); if (arch == null) { EntityArchetypeHashLabel.Text += " (not found)"; } TreeNode tn = FindEntityTreeNode(CurrentEntity); if (tn != null) { tn.Text = name; } if (CurrentEntity != null) { lock (ymapsyncroot) { CurrentEntity._CEntityDef.archetypeName = new MetaHash(hash); if (CurrentEntity.Archetype != arch) { CurrentEntity.SetArchetype(arch); SetYmapHasChanged(true); } } } } private void EntityFlagsTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; uint flags = 0; uint.TryParse(EntityFlagsTextBox.Text, out flags); populatingui = true; for (int i = 0; i < EntityFlagsCheckedListBox.Items.Count; i++) { var c = ((flags & (1u << i)) > 0); EntityFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.flags != flags) { CurrentEntity._CEntityDef.flags = flags; SetYmapHasChanged(true); } } } private void EntityFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; uint flags = 0; for (int i = 0; i < EntityFlagsCheckedListBox.Items.Count; i++) { if (e.Index == i) { if (e.NewValue == CheckState.Checked) { flags += (uint)(1 << i); } } else { if (EntityFlagsCheckedListBox.GetItemChecked(i)) { flags += (uint)(1 << i); } } } populatingui = true; EntityFlagsTextBox.Text = flags.ToString(); populatingui = false; lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.flags != flags) { CurrentEntity._CEntityDef.flags = flags; SetYmapHasChanged(true); } } } private void EntityGuidTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; uint guid = 0; uint.TryParse(EntityGuidTextBox.Text, out guid); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.guid != guid) { CurrentEntity._CEntityDef.guid = guid; SetYmapHasChanged(true); } } } private void EntityPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; Vector3 v = FloatUtil.ParseVector3String(EntityPositionTextBox.Text); lock (ymapsyncroot) { if (CurrentEntity.MloParent != null) { //TODO: positioning for interior entities! } else { if (CurrentEntity.Position != v) { CurrentEntity.SetPosition(v); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.BeginInvoke(new Action(() => { WorldForm.SetWidgetPosition(CurrentEntity.WidgetPosition, true); })); } } } } } private void EntityRotationTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; Vector4 v = FloatUtil.ParseVector4String(EntityRotationTextBox.Text); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.rotation != v) { Quaternion q = new Quaternion(v); CurrentEntity.SetOrientationInv(q); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.BeginInvoke(new Action(() => { WorldForm.SetWidgetRotation(CurrentEntity.WidgetOrientation, true); })); } } } } private void EntityScaleXYTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; float sxy = 0; FloatUtil.TryParse(EntityScaleXYTextBox.Text, out sxy); lock (ymapsyncroot) { if (CurrentEntity.Scale.X != sxy) { Vector3 newscale = new Vector3(sxy, sxy, CurrentEntity.Scale.Z); CurrentEntity.SetScale(newscale); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.BeginInvoke(new Action(() => { WorldForm.SetWidgetScale(newscale, true); })); } } } } private void EntityScaleZTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; float sz = 0; FloatUtil.TryParse(EntityScaleZTextBox.Text, out sz); lock (ymapsyncroot) { if (CurrentEntity.Scale.Z != sz) { Vector3 newscale = new Vector3(CurrentEntity.Scale.X, CurrentEntity.Scale.Y, sz); CurrentEntity.SetScale(newscale); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.BeginInvoke(new Action(() => { WorldForm.SetWidgetScale(newscale, true); })); } } } } private void EntityParentIndexTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; int pind = 0; int.TryParse(EntityParentIndexTextBox.Text, out pind); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.parentIndex != pind) { CurrentEntity._CEntityDef.parentIndex = pind; //Needs more work for LOD linking! SetYmapHasChanged(true); } } } private void EntityLodDistTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; float lodDist = 0; FloatUtil.TryParse(EntityLodDistTextBox.Text, out lodDist); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.lodDist != lodDist) { CurrentEntity._CEntityDef.lodDist = lodDist; SetYmapHasChanged(true); } } } private void EntityChildLodDistTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; float childLodDist = 0; FloatUtil.TryParse(EntityChildLodDistTextBox.Text, out childLodDist); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.childLodDist != childLodDist) { CurrentEntity._CEntityDef.childLodDist = childLodDist; SetYmapHasChanged(true); } } } private void EntityLodLevelComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; Unk_1264241711 lodLevel = (Unk_1264241711)EntityLodLevelComboBox.SelectedItem; lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.lodLevel != lodLevel) { CurrentEntity._CEntityDef.lodLevel = lodLevel; SetYmapHasChanged(true); } } } private void EntityNumChildrenTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; uint numChildren = 0; uint.TryParse(EntityNumChildrenTextBox.Text, out numChildren); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.numChildren != numChildren) { CurrentEntity._CEntityDef.numChildren = numChildren; SetYmapHasChanged(true); } } } private void EntityPriorityLevelComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; Unk_648413703 priorityLevel = (Unk_648413703)EntityPriorityLevelComboBox.SelectedItem; lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.priorityLevel != priorityLevel) { CurrentEntity._CEntityDef.priorityLevel = priorityLevel; SetYmapHasChanged(true); } } } private void EntityAOMultiplierTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; int aomult = 0; int.TryParse(EntityAOMultiplierTextBox.Text, out aomult); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.ambientOcclusionMultiplier != aomult) { CurrentEntity._CEntityDef.ambientOcclusionMultiplier = aomult; SetYmapHasChanged(true); } } } private void EntityArtificialAOTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; int artao = 0; int.TryParse(EntityArtificialAOTextBox.Text, out artao); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.artificialAmbientOcclusion != artao) { CurrentEntity._CEntityDef.artificialAmbientOcclusion = artao; SetYmapHasChanged(true); } } } private void EntityTintValueTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; uint tintValue = 0; uint.TryParse(EntityTintValueTextBox.Text, out tintValue); lock (ymapsyncroot) { if (CurrentEntity._CEntityDef.tintValue != tintValue) { CurrentEntity._CEntityDef.tintValue = tintValue; SetYmapHasChanged(true); } } } private void EntityGoToButton_Click(object sender, EventArgs e) { if (CurrentEntity == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentEntity.Position); } private void EntityNormalizeRotationButton_Click(object sender, EventArgs e) { Vector4 v = FloatUtil.ParseVector4String(EntityRotationTextBox.Text); Quaternion q = Quaternion.Normalize(new Quaternion(v)); EntityRotationTextBox.Text = FloatUtil.GetVector4String(new Vector4(q.X, q.Y, q.Z, q.W)); } private void EntityAddToProjectButton_Click(object sender, EventArgs e) { AddEntityToProject(); } private void EntityDeleteButton_Click(object sender, EventArgs e) { DeleteEntity(); } private void EntityPivotEditCheckBox_CheckedChanged(object sender, EventArgs e) { if (WorldForm != null) { WorldForm.EditEntityPivot = EntityPivotEditCheckBox.Checked; } } private void EntityPivotPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; Vector3 v = FloatUtil.ParseVector3String(EntityPivotPositionTextBox.Text); lock (ymapsyncroot) { if (CurrentEntity.PivotPosition != v) { CurrentEntity.SetPivotPosition(v); //SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.BeginInvoke(new Action(() => { bool editpivot = WorldForm.EditEntityPivot; WorldForm.EditEntityPivot = true; WorldForm.SetWidgetPosition(CurrentEntity.WidgetPosition, true); WorldForm.EditEntityPivot = editpivot; })); } } } } private void EntityPivotRotationTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentEntity == null) return; Vector4 v = FloatUtil.ParseVector4String(EntityPivotRotationTextBox.Text); Quaternion q = new Quaternion(v); lock (ymapsyncroot) { if (CurrentEntity.PivotOrientation != q) { CurrentEntity.SetPivotOrientation(q); //SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.BeginInvoke(new Action(() => { bool editpivot = WorldForm.EditEntityPivot; WorldForm.EditEntityPivot = true; WorldForm.SetWidgetRotation(CurrentEntity.WidgetOrientation, true); WorldForm.EditEntityPivot = editpivot; })); } } } } private void EntityPivotRotationNormalizeButton_Click(object sender, EventArgs e) { Vector4 v = FloatUtil.ParseVector4String(EntityPivotRotationTextBox.Text); Quaternion q = Quaternion.Normalize(new Quaternion(v)); EntityPivotRotationTextBox.Text = FloatUtil.GetVector4String(new Vector4(q.X, q.Y, q.Z, q.W)); } private void CarModelTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; uint hash = 0; string name = CarModelTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } CarModelHashLabel.Text = "Hash: " + hash.ToString(); //var model = GameFileCache.GetCarInfo(hash); //todo: something like this for car info? //if (model == null) //{ // CarModelHashLabel.Text += " (not found)"; //} if (CurrentCarGen != null) { lock (ymapsyncroot) { var modelhash = new MetaHash(hash); if (CurrentCarGen._CCarGen.carModel != modelhash) { CurrentCarGen._CCarGen.carModel = modelhash; SetYmapHasChanged(true); } } } UpdateCarGenTreeNode(CurrentCarGen); } private void CarPopGroupTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; uint hash = 0; string name = CarPopGroupTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } CarPopGroupHashLabel.Text = "Hash: " + hash.ToString(); //var grp = GameFileCache.GetCarPopGroup(hash); //todo: something like this for popgroup info? //if (grp == null) //{ // CarPopGroupHashLabel.Text += " (not found)"; //} if (CurrentCarGen != null) { lock (ymapsyncroot) { var pghash = new MetaHash(hash); if (CurrentCarGen._CCarGen.popGroup != pghash) { CurrentCarGen._CCarGen.popGroup = pghash; SetYmapHasChanged(true); } } } UpdateCarGenTreeNode(CurrentCarGen); } private void CarFlagsTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; uint flags = 0; uint.TryParse(CarFlagsTextBox.Text, out flags); populatingui = true; for (int i = 0; i < CarFlagsCheckedListBox.Items.Count; i++) { var c = ((flags & (1u << i)) > 0); CarFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.flags != flags) { CurrentCarGen._CCarGen.flags = flags; SetYmapHasChanged(true); } } } private void CarFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; uint flags = 0; for (int i = 0; i < CarFlagsCheckedListBox.Items.Count; i++) { if (e.Index == i) { if (e.NewValue == CheckState.Checked) { flags += (uint)(1 << i); } } else { if (CarFlagsCheckedListBox.GetItemChecked(i)) { flags += (uint)(1 << i); } } } populatingui = true; CarFlagsTextBox.Text = flags.ToString(); populatingui = false; lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.flags != flags) { CurrentCarGen._CCarGen.flags = flags; SetYmapHasChanged(true); } } } private void CarPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; Vector3 v = FloatUtil.ParseVector3String(CarPositionTextBox.Text); lock (ymapsyncroot) { if (CurrentCarGen.Position != v) { CurrentCarGen.SetPosition(v); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.SetWidgetPosition(v); } } } UpdateCarGenTreeNode(CurrentCarGen); } private void CarOrientXTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; float ox = FloatUtil.Parse(CarOrientXTextBox.Text); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.orientX != ox) { CurrentCarGen._CCarGen.orientX = ox; CurrentCarGen.CalcOrientation(); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.SetWidgetRotation(CurrentCarGen.Orientation); } } } } private void CarOrientYTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; float oy = FloatUtil.Parse(CarOrientYTextBox.Text); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.orientY != oy) { CurrentCarGen._CCarGen.orientY = oy; CurrentCarGen.CalcOrientation(); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.SetWidgetRotation(CurrentCarGen.Orientation); } } } } private void CarPerpendicularLengthTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; float len = FloatUtil.Parse(CarPerpendicularLengthTextBox.Text); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.perpendicularLength != len) { CurrentCarGen.SetLength(len); SetYmapHasChanged(true); if (WorldForm != null) { WorldForm.SetWidgetScale(new Vector3(len)); } } } } private void CarBodyColorRemap1TextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; int cr = 0; int.TryParse(CarBodyColorRemap1TextBox.Text, out cr); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.bodyColorRemap1 != cr) { CurrentCarGen._CCarGen.bodyColorRemap1 = cr; SetYmapHasChanged(true); } } } private void CarBodyColorRemap2TextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; int cr = 0; int.TryParse(CarBodyColorRemap2TextBox.Text, out cr); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.bodyColorRemap2 != cr) { CurrentCarGen._CCarGen.bodyColorRemap2 = cr; SetYmapHasChanged(true); } } } private void CarBodyColorRemap3TextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; int cr = 0; int.TryParse(CarBodyColorRemap3TextBox.Text, out cr); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.bodyColorRemap3 != cr) { CurrentCarGen._CCarGen.bodyColorRemap3 = cr; SetYmapHasChanged(true); } } } private void CarBodyColorRemap4TextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; int cr = 0; int.TryParse(CarBodyColorRemap4TextBox.Text, out cr); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.bodyColorRemap4 != cr) { CurrentCarGen._CCarGen.bodyColorRemap4 = cr; SetYmapHasChanged(true); } } } private void CarLiveryTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentCarGen == null) return; sbyte cr = 0; sbyte.TryParse(CarLiveryTextBox.Text, out cr); lock (ymapsyncroot) { if (CurrentCarGen._CCarGen.livery != cr) { CurrentCarGen._CCarGen.livery = cr; SetYmapHasChanged(true); } } UpdateCarGenTreeNode(CurrentCarGen); } private void CarGoToButton_Click(object sender, EventArgs e) { if (CurrentCarGen == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentCarGen.Position); } private void CarAddToProjectButton_Click(object sender, EventArgs e) { AddCarGenToProject(); } private void CarDeleteButton_Click(object sender, EventArgs e) { DeleteCarGen(); } private void YndAreaIDUpDownChange() { if (populatingui) return; if (CurrentYndFile == null) return; int x = (int)YndAreaIDXUpDown.Value; int y = (int)YndAreaIDYUpDown.Value; lock (yndsyncroot) { var areaid = y * 32 + x; if (CurrentYndFile.AreaID != areaid) { CurrentYndFile.AreaID = areaid; CurrentYndFile.Name = "nodes" + areaid.ToString() + ".ynd"; YndAreaIDInfoLabel.Text = "ID: " + areaid.ToString(); SetYndHasChanged(true); } } } private void YndAreaIDXUpDown_ValueChanged(object sender, EventArgs e) { YndAreaIDUpDownChange(); } private void YndAreaIDYUpDown_ValueChanged(object sender, EventArgs e) { YndAreaIDUpDownChange(); } private void YndVehicleNodesUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentYndFile == null) return; if (CurrentYndFile.NodeDictionary == null) return; lock (yndsyncroot) { var vehnodes = (int)YndVehicleNodesUpDown.Value; if (CurrentYndFile.NodeDictionary.NodesCountVehicle != vehnodes) { CurrentYndFile.NodeDictionary.NodesCountVehicle = (uint)vehnodes; SetYndHasChanged(true); } } } private void YndPedNodesUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentYndFile == null) return; if (CurrentYndFile.NodeDictionary == null) return; lock (yndsyncroot) { var pednodes = (int)YndPedNodesUpDown.Value; if (CurrentYndFile.NodeDictionary.NodesCountPed != pednodes) { CurrentYndFile.NodeDictionary.NodesCountPed = (uint)pednodes; SetYndHasChanged(true); } } } private void PathNodeAreaIDUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; ushort areaid = (ushort)PathNodeAreaIDUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.AreaID != areaid) { CurrentPathNode.AreaID = areaid; SetYndHasChanged(true); } } UpdatePathNodeTreeNode(CurrentPathNode); } private void PathNodeNodeIDUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; ushort nodeid = (ushort)PathNodeNodeIDUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.NodeID != nodeid) { CurrentPathNode.NodeID = nodeid; SetYndHasChanged(true); } } UpdatePathNodeTreeNode(CurrentPathNode); } private void PathNodePositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; Vector3 v = FloatUtil.ParseVector3String(PathNodePositionTextBox.Text); bool change = false; lock (yndsyncroot) { if (CurrentPathNode.Position != v) { CurrentPathNode.SetPosition(v); SetYndHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentPathNode.Position); WorldForm.UpdatePathNodeGraphics(CurrentPathNode, false); } //PathNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentPathNode.Position); } } private void PathNodeGoToButton_Click(object sender, EventArgs e) { if (CurrentPathNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentPathNode.Position); } private void PathNodeAddToProjectButton_Click(object sender, EventArgs e) { AddPathNodeToProject(); } private void PathNodeDeleteButton_Click(object sender, EventArgs e) { DeletePathNode(); } private void PathNodeStreetHashTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; uint hash; uint.TryParse(PathNodeStreetHashTextBox.Text, out hash); var streetname = GlobalText.TryGetString(hash); PathNodeStreetNameLabel.Text = "Name: " + ((hash == 0) ? "[None]" : (string.IsNullOrEmpty(streetname) ? "[Not found]" : streetname)); lock (yndsyncroot) { if (CurrentPathNode.StreetName.Hash != hash) { CurrentPathNode.StreetName = hash; SetYndHasChanged(true); } } UpdatePathNodeTreeNode(CurrentPathNode); } private void PathNodeFlags0UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromUpDowns(); } private void PathNodeFlags1UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromUpDowns(); } private void PathNodeFlags2UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromUpDowns(); } private void PathNodeFlags3UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromUpDowns(); } private void PathNodeFlags4UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromUpDowns(); } private void PathNodeFlags5UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromUpDowns(); } private void PathNodeFlags01CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags02CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags03CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags04CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags05CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags06CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags07CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags08CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags11CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags12CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags13CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags14CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags15CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags16CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags17CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags18CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags21CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags22CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags23CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags24CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags25CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags26CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags27CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags28CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags31CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags32UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); //treat this one like checkboxes } private void PathNodeFlags51CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags41CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags45CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags46CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags47CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags48CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags42UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); //treat this one like checkboxes } private void PathNodeFlags52CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeFlags53CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeFlagsFromCheckBoxes(); } private void PathNodeLinksListBox_SelectedIndexChanged(object sender, EventArgs e) { CurrentPathLink = PathNodeLinksListBox.SelectedItem as YndLink; LoadPathNodeLinkPage(); } private void PathNodeAddLinkButton_Click(object sender, EventArgs e) { AddPathLink(); } private void PathNodeRemoveLinkButton_Click(object sender, EventArgs e) { RemovePathLink(); } private void PathNodeLinkAreaIDUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathLink == null) return; ushort areaid = (ushort)PathNodeLinkAreaIDUpDown.Value; bool change = false; lock (yndsyncroot) { if (CurrentPathLink._RawData.AreaID != areaid) { CurrentPathLink._RawData.AreaID = areaid; SetYndHasChanged(true); change = true; } } if (change) { UpdatePathNodeLinkage(); //refresh the selected item in the list box, to update the text, and the other controls. PathNodeLinksListBox.Items[PathNodeLinksListBox.SelectedIndex] = PathNodeLinksListBox.SelectedItem; } } private void PathNodeLinkNodeIDUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathLink == null) return; ushort nodeid = (ushort)PathNodeLinkNodeIDUpDown.Value; bool change = false; lock (yndsyncroot) { if (CurrentPathLink._RawData.NodeID != nodeid) { CurrentPathLink._RawData.NodeID = nodeid; SetYndHasChanged(true); change = true; } } if (change) { UpdatePathNodeLinkage(); //refresh the selected item in the list box, to update the text, and the other controls. PathNodeLinksListBox.Items[PathNodeLinksListBox.SelectedIndex] = PathNodeLinksListBox.SelectedItem; } } private void PathNodeLinkFlags0UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromUpDowns(); } private void PathNodeLinkFlags1UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromUpDowns(); } private void PathNodeLinkFlags2UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromUpDowns(); } private void PathNodeLinkFlags01CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags02CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags03UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags04UpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags11CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags12CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags13CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags14CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags18CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkOffsetSizeUpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags21CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFlags22CheckBox_CheckedChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkFwdLanesUpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkBackLanesUpDown_ValueChanged(object sender, EventArgs e) { SetPathNodeLinkFlagsFromCheckBoxes(); } private void PathNodeLinkLengthUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathLink == null) return; byte length = (byte)PathNodeLinkLengthUpDown.Value; lock (yndsyncroot) { if (CurrentPathLink.LinkLength.Value != length) { CurrentPathLink.LinkLength = length; CurrentPathLink._RawData.LinkLength = length; SetYndHasChanged(true); } } } private void PathNodeJunctionEnableCheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; lock (yndsyncroot) { if (CurrentPathNode.HasJunction != PathNodeJunctionEnableCheckBox.Checked) { CurrentPathNode.HasJunction = PathNodeJunctionEnableCheckBox.Checked; if (CurrentPathNode.HasJunction && (CurrentPathNode.Junction == null)) { var j = new YndJunction(); //init new junction j._RawData.HeightmapDimX = 1; j._RawData.HeightmapDimY = 1; j.Heightmap = new YndJunctionHeightmap(new byte[] { 255 }, j); j.RefData = new NodeJunctionRef() { AreaID = (ushort)CurrentPathNode.AreaID, NodeID = (ushort)CurrentPathNode.NodeID }; CurrentPathNode.Junction = j; } SetYndHasChanged(true); } } LoadPathNodeJunctionPage(); } private void PathNodeJunctionMaxZUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; short val = (short)PathNodeJunctionMaxZUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Junction.MaxZ != val) { CurrentPathNode.Junction.MaxZ = val; CurrentPathNode.Junction._RawData.MaxZ = val; SetYndHasChanged(true); } } } private void PathNodeJunctionMinZUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; short val = (short)PathNodeJunctionMinZUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Junction.MinZ != val) { CurrentPathNode.Junction.MinZ = val; CurrentPathNode.Junction._RawData.MinZ = val; SetYndHasChanged(true); } } } private void PathNodeJunctionPosXUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; short val = (short)PathNodeJunctionPosXUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Junction.PositionX != val) { CurrentPathNode.Junction.PositionX = val; CurrentPathNode.Junction._RawData.PositionX = val; SetYndHasChanged(true); } } } private void PathNodeJunctionPosYUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; short val = (short)PathNodeJunctionPosYUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Junction.PositionY != val) { CurrentPathNode.Junction.PositionY = val; CurrentPathNode.Junction._RawData.PositionY = val; SetYndHasChanged(true); } } } private void PathNodeJunctionHeightmapDimXUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; byte val = (byte)PathNodeJunctionHeightmapDimXUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Junction._RawData.HeightmapDimX != val) { CurrentPathNode.Junction._RawData.HeightmapDimX = val; CurrentPathNode.Junction.ResizeHeightmap(); SetYndHasChanged(true); } } LoadPathNodeJunctionPage(); } private void PathNodeJunctionHeightmapDimYUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; byte val = (byte)PathNodeJunctionHeightmapDimYUpDown.Value; lock (yndsyncroot) { if (CurrentPathNode.Junction._RawData.HeightmapDimY != val) { CurrentPathNode.Junction._RawData.HeightmapDimY = val; CurrentPathNode.Junction.ResizeHeightmap(); SetYndHasChanged(true); } } LoadPathNodeJunctionPage(); } private void PathNodeJunctionHeightmapBytesTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentPathNode == null) return; if (CurrentPathNode.Junction == null) return; lock (yndsyncroot) { CurrentPathNode.Junction.SetHeightmap(PathNodeJunctionHeightmapBytesTextBox.Text); SetYndHasChanged(true); } //LoadPathNodeJunctionPage(); } private void TrainNodePositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentTrainNode == null) return; Vector3 v = FloatUtil.ParseVector3String(TrainNodePositionTextBox.Text); bool change = false; lock (trainsyncroot) { if (CurrentTrainNode.Position != v) { CurrentTrainNode.SetPosition(v); SetTrainTrackHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentTrainNode.Position); WorldForm.UpdateTrainTrackNodeGraphics(CurrentTrainNode, false); } //TrainNodePositionTextBox.Text = FloatUtil.GetVector3String(CurrentTrainNode.Position); } } private void TrainNodeGoToButton_Click(object sender, EventArgs e) { if (CurrentTrainNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentTrainNode.Position); } private void TrainNodeTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentTrainNode == null) return; int type = TrainNodeTypeComboBox.SelectedIndex; bool change = false; lock (trainsyncroot) { if (CurrentTrainNode.NodeType != type) { CurrentTrainNode.NodeType = type; SetTrainTrackHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.UpdateTrainTrackNodeGraphics(CurrentTrainNode, false); //change the colour... } } UpdateTrainNodeTreeNode(CurrentTrainNode); } private void TrainNodeAddToProjectButton_Click(object sender, EventArgs e) { AddTrainNodeToProject(); } private void TrainNodeDeleteButton_Click(object sender, EventArgs e) { DeleteTrainNode(); } private void ScenarioYmtVersionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenario == null) return; if (CurrentScenario.CScenarioPointRegion == null) return; lock (scenariosyncroot) { int v = 0; int.TryParse(ScenarioYmtVersionTextBox.Text, out v); if (CurrentScenario.CScenarioPointRegion.VersionNumber != v) { CurrentScenario.CScenarioPointRegion.VersionNumber = v; SetScenarioHasChanged(true); } } } private void ScenarioPointCheckBox_CheckedChanged(object sender, EventArgs e) { } private void ScenarioPointAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioPointDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioNode(); } private void ScenarioPointGoToButton_Click(object sender, EventArgs e) { if (CurrentScenarioNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentScenarioNode.Position); } private void ScenarioPointPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; Vector3 v = FloatUtil.ParseVector3String(ScenarioPointPositionTextBox.Text); bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.Position != v) { CurrentScenarioNode.SetPosition(v); SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioPointDirectionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; float dir = FloatUtil.Parse(ScenarioPointDirectionTextBox.Text); lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.Direction != dir) { CurrentScenarioNode.MyPoint.Direction = dir; CurrentScenarioNode.Orientation = CurrentScenarioNode.MyPoint.Orientation; SetScenarioHasChanged(true); if (WorldForm != null) { WorldForm.SetWidgetRotation(CurrentScenarioNode.Orientation); } } } } private void ScenarioPointTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; ScenarioType stype = ScenarioPointTypeComboBox.SelectedItem as ScenarioType; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.Type != stype) { CurrentScenarioNode.MyPoint.Type = stype; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); if (CurrentScenarioNode.ChainingNode != null) { ScenarioChainNodeTypeComboBox.SelectedItem = stype; } } private void ScenarioPointModelSetComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; AmbientModelSet mset = ScenarioPointModelSetComboBox.SelectedItem as AmbientModelSet; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.ModelSet != mset) { CurrentScenarioNode.MyPoint.ModelSet = mset; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioPointInteriorTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; uint hash = 0; string name = ScenarioPointInteriorTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioPointInteriorHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.InteriorName != hash) { CurrentScenarioNode.MyPoint.InteriorName = hash; SetScenarioHasChanged(true); } } } private void ScenarioPointGroupTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; uint hash = 0; string name = ScenarioPointGroupTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioPointGroupHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.GroupName != hash) { CurrentScenarioNode.MyPoint.GroupName = hash; SetScenarioHasChanged(true); } } } private void ScenarioPointImapTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; uint hash = 0; string name = ScenarioPointImapTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioPointImapHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.IMapName != hash) { CurrentScenarioNode.MyPoint.IMapName = hash; SetScenarioHasChanged(true); } } } private void ScenarioPointTimeStartUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; byte t = (byte)ScenarioPointTimeStartUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.TimeStart != t) { CurrentScenarioNode.MyPoint.TimeStart = t; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioPointTimeEndUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; byte t = (byte)ScenarioPointTimeEndUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.TimeEnd != t) { CurrentScenarioNode.MyPoint.TimeEnd = t; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioPointProbabilityUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; byte v = (byte)ScenarioPointProbabilityUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.Probability != v) { CurrentScenarioNode.MyPoint.Probability = v; SetScenarioHasChanged(true); } } } private void ScenarioPointSpOnlyFlagUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; byte v = (byte)ScenarioPointSpOnlyFlagUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.AvailableMpSp != v) { CurrentScenarioNode.MyPoint.AvailableMpSp = v; SetScenarioHasChanged(true); } } } private void ScenarioPointRadiusUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; byte v = (byte)ScenarioPointRadiusUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.Radius != v) { CurrentScenarioNode.MyPoint.Radius = v; SetScenarioHasChanged(true); } } } private void ScenarioPointWaitTimeUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; byte v = (byte)ScenarioPointWaitTimeUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.WaitTime != v) { CurrentScenarioNode.MyPoint.WaitTime = v; SetScenarioHasChanged(true); } } } private void ScenarioPointFlagsValueUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; var iflags = (uint)ScenarioPointFlagsValueUpDown.Value; populatingui = true; for (int i = 0; i < ScenarioPointFlagsCheckedListBox.Items.Count; i++) { var c = ((iflags & (1 << i)) > 0); ScenarioPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; Unk_700327466 f = (Unk_700327466)iflags; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.Flags != f) { CurrentScenarioNode.MyPoint.Flags = f; SetScenarioHasChanged(true); } } } private void ScenarioPointFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.MyPoint == null) return; uint iflags = 0; for (int i = 0; i < ScenarioPointFlagsCheckedListBox.Items.Count; i++) { if (e.Index == i) { if (e.NewValue == CheckState.Checked) { iflags += (uint)(1 << i); } } else { if (ScenarioPointFlagsCheckedListBox.GetItemChecked(i)) { iflags += (uint)(1 << i); } } } populatingui = true; ScenarioPointFlagsValueUpDown.Value = iflags; populatingui = false; Unk_700327466 f = (Unk_700327466)iflags; lock (scenariosyncroot) { if (CurrentScenarioNode.MyPoint.Flags != f) { CurrentScenarioNode.MyPoint.Flags = f; SetScenarioHasChanged(true); } } } private void ScenarioEntityCheckBox_CheckedChanged(object sender, EventArgs e) { } private void ScenarioEntityAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioEntityDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioEntity(); } private void ScenarioEntityGoToButton_Click(object sender, EventArgs e) { if (CurrentScenarioNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentScenarioNode.Position); } private void ScenarioEntityPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Entity == null) return; Vector3 v = FloatUtil.ParseVector3String(ScenarioEntityPositionTextBox.Text); bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.Position != v) { CurrentScenarioNode.SetPosition(v); SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioEntityTypeTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Entity == null) return; uint hash = 0; string name = ScenarioEntityTypeTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityTypeHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.Entity.TypeName != hash) { CurrentScenarioNode.Entity.TypeName = hash; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioEntityUnk1UpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Entity == null) return; byte v = (byte)ScenarioEntityUnk1UpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.Entity.Unk1 != v) { CurrentScenarioNode.Entity.Unk1 = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityUnk2UpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Entity == null) return; byte v = (byte)ScenarioEntityUnk2UpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.Entity.Unk2 != v) { CurrentScenarioNode.Entity.Unk2 = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointsListBox_DoubleClick(object sender, EventArgs e) { var item = ScenarioEntityPointsListBox.SelectedItem as MCExtensionDefSpawnPoint; if (item == null) return; var nodes = CurrentScenario?.ScenarioRegion?.Nodes; if (nodes == null) return; ScenarioNode node = null; foreach (var snode in nodes) { if (snode.EntityPoint == item) { node = snode; break; } } if (node == null) return; TrySelectScenarioNodeTreeNode(node); } private void ScenarioEntityAddPointButton_Click(object sender, EventArgs e) { AddScenarioEntityPoint(); } private void ScenarioEntityPointCheckBox_CheckedChanged(object sender, EventArgs e) { } private void ScenarioEntityPointAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioEntityPointDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioNode(); } private void ScenarioEntityPointGoToButton_Click(object sender, EventArgs e) { if (CurrentScenarioNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentScenarioNode.Position); } private void ScenarioEntityPointPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; Vector3 v = FloatUtil.ParseVector3String(ScenarioEntityPointPositionTextBox.Text); v += CurrentScenarioNode.EntityPoint.ParentPosition; bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.Position != v) { CurrentScenarioNode.SetPosition(v); SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioEntityPointRotationTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; Vector4 v = FloatUtil.ParseVector4String(ScenarioEntityPointRotationTextBox.Text); bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.OffsetRotation != v) { CurrentScenarioNode.EntityPoint.OffsetRotation = v; CurrentScenarioNode.Orientation = new Quaternion(v); SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetRotation(CurrentScenarioNode.Orientation); } } } private void ScenarioEntityPointNameTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint hash = 0; string name = ScenarioEntityPointNameTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityPointNameHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.NameHash != hash) { CurrentScenarioNode.EntityPoint.NameHash = hash; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioEntityPointSpawnTypeTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint hash = 0; string name = ScenarioEntityPointSpawnTypeTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityPointSpawnTypeHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.SpawnType != hash) { CurrentScenarioNode.EntityPoint.SpawnType = hash; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioEntityPointPedTypeTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint hash = 0; string name = ScenarioEntityPointPedTypeTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityPointPedTypeHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.PedType != hash) { CurrentScenarioNode.EntityPoint.PedType = hash; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioEntityPointGroupTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint hash = 0; string name = ScenarioEntityPointGroupTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityPointGroupHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.Group != hash) { CurrentScenarioNode.EntityPoint.Group = hash; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointInteriorTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint hash = 0; string name = ScenarioEntityPointInteriorTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityPointInteriorHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.Interior != hash) { CurrentScenarioNode.EntityPoint.Interior = hash; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointRequiredImapTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint hash = 0; string name = ScenarioEntityPointRequiredImapTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioEntityPointRequiredImapHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.RequiredImap != hash) { CurrentScenarioNode.EntityPoint.RequiredImap = hash; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointAvailableInMpSpComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; Unk_3573596290 v = (Unk_3573596290)ScenarioEntityPointAvailableInMpSpComboBox.SelectedItem; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.AvailableInMpSp != v) { CurrentScenarioNode.EntityPoint.AvailableInMpSp = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointProbabilityTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; float v = FloatUtil.Parse(ScenarioEntityPointProbabilityTextBox.Text); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.Probability != v) { CurrentScenarioNode.EntityPoint.Probability = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointTimeTillPedLeavesTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; float v = FloatUtil.Parse(ScenarioEntityPointTimeTillPedLeavesTextBox.Text); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.TimeTillPedLeaves != v) { CurrentScenarioNode.EntityPoint.TimeTillPedLeaves = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointRadiusTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; float v = FloatUtil.Parse(ScenarioEntityPointRadiusTextBox.Text); lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.Radius != v) { CurrentScenarioNode.EntityPoint.Radius = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointStartUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; byte v = (byte)ScenarioEntityPointStartUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.StartTime != v) { CurrentScenarioNode.EntityPoint.StartTime = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointEndUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; byte v = (byte)ScenarioEntityPointEndUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.EndTime != v) { CurrentScenarioNode.EntityPoint.EndTime = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointExtendedRangeCheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; bool v = ScenarioEntityPointExtendedRangeCheckBox.Checked; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.ExtendedRange != v) { CurrentScenarioNode.EntityPoint.ExtendedRange = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointShortRangeCheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; bool v = ScenarioEntityPointShortRangeCheckBox.Checked; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.ShortRange != v) { CurrentScenarioNode.EntityPoint.ShortRange = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointHighPriCheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; bool v = ScenarioEntityPointHighPriCheckBox.Checked; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.HighPri != v) { CurrentScenarioNode.EntityPoint.HighPri = v; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointFlagsUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; var iflags = (uint)ScenarioEntityPointFlagsUpDown.Value; populatingui = true; for (int i = 0; i < ScenarioEntityPointFlagsCheckedListBox.Items.Count; i++) { var c = ((iflags & (1 << i)) > 0); ScenarioEntityPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; Unk_700327466 f = (Unk_700327466)iflags; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.Flags != f) { CurrentScenarioNode.EntityPoint.Flags = f; SetScenarioHasChanged(true); } } } private void ScenarioEntityPointFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.EntityPoint == null) return; uint iflags = 0; for (int i = 0; i < ScenarioEntityPointFlagsCheckedListBox.Items.Count; i++) { if (e.Index == i) { if (e.NewValue == CheckState.Checked) { iflags += (uint)(1 << i); } } else { if (ScenarioEntityPointFlagsCheckedListBox.GetItemChecked(i)) { iflags += (uint)(1 << i); } } } populatingui = true; ScenarioEntityPointFlagsUpDown.Value = iflags; populatingui = false; Unk_700327466 f = (Unk_700327466)iflags; lock (scenariosyncroot) { if (CurrentScenarioNode.EntityPoint.Flags != f) { CurrentScenarioNode.EntityPoint.Flags = f; SetScenarioHasChanged(true); } } } private void ScenarioChainNodeCheckBox_CheckedChanged(object sender, EventArgs e) { } private void ScenarioChainNodeAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioChainNodeDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioNode(); } private void ScenarioChainNodeGoToButton_Click(object sender, EventArgs e) { if (CurrentScenarioNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentScenarioNode.Position); } private void ScenarioChainNodePositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; Vector3 v = FloatUtil.ParseVector3String(ScenarioChainNodePositionTextBox.Text); bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.Position != v) { CurrentScenarioNode.SetPosition(v); SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioChainNodeUnk1TextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ChainingNode == null) return; uint hash = 0; string name = ScenarioChainNodeUnk1TextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioChainNodeUnk1HashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.ChainingNode.Unk1 != hash) { CurrentScenarioNode.ChainingNode.Unk1 = hash; SetScenarioHasChanged(true); } } } private void ScenarioChainNodeTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ChainingNode == null) return; ScenarioType stype = ScenarioChainNodeTypeComboBox.SelectedItem as ScenarioType; lock (scenariosyncroot) { if (CurrentScenarioNode.ChainingNode.Type != stype) { CurrentScenarioNode.ChainingNode.Type = stype; CurrentScenarioNode.ChainingNode.TypeHash = stype?.NameHash ?? 0; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioChainNodeFirstCheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ChainingNode == null) return; bool v = !ScenarioChainNodeFirstCheckBox.Checked; bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.ChainingNode.NotFirst != v) { CurrentScenarioNode.ChainingNode.NotFirst = v; SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioChainNodeLastCheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ChainingNode == null) return; bool v = !ScenarioChainNodeLastCheckBox.Checked; bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.ChainingNode.NotLast != v) { CurrentScenarioNode.ChainingNode.NotLast = v; SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioChainAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioChainDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioChain(); } private void ScenarioChainEdgesListBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; CurrentScenarioChainEdge = ScenarioChainEdgesListBox.SelectedItem as MCScenarioChainingEdge; populatingui = true; LoadScenarioChainEdgeTabPage(); populatingui = false; } private void ScenarioChainAddEdgeButton_Click(object sender, EventArgs e) { AddScenarioEdge(); } private void ScenarioChainRemoveEdgeButton_Click(object sender, EventArgs e) { RemoveScenarioEdge(); } private void ScenarioChainMoveEdgeUpButton_Click(object sender, EventArgs e) { MoveScenarioEdge(false); } private void ScenarioChainMoveEdgeDownButton_Click(object sender, EventArgs e) { MoveScenarioEdge(true); } private void ScenarioChainUnk1UpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ChainingNode == null) return; if (CurrentScenarioNode.ChainingNode.Chain == null) return; byte v = (byte)ScenarioChainUnk1UpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ChainingNode.Chain.Unk1 != v) { CurrentScenarioNode.ChainingNode.Chain.Unk1 = v; SetScenarioHasChanged(true); } } } private void ScenarioChainEdgeNodeIndexFromUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioChainEdge == null) return; ushort nodeid = (ushort)ScenarioChainEdgeNodeIndexFromUpDown.Value; bool change = false; lock (scenariosyncroot) { if (CurrentScenarioChainEdge.NodeIndexFrom != nodeid) { CurrentScenarioChainEdge.NodeIndexFrom = nodeid; SetScenarioHasChanged(true); change = true; } } if (change) { UpdateScenarioEdgeLinkage(); //refresh the selected item in the list box, to update the text, and the other controls. ScenarioChainEdgesListBox.Items[ScenarioChainEdgesListBox.SelectedIndex] = ScenarioChainEdgesListBox.SelectedItem; } } private void ScenarioChainEdgeNodeIndexToUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioChainEdge == null) return; ushort nodeid = (ushort)ScenarioChainEdgeNodeIndexToUpDown.Value; bool change = false; lock (scenariosyncroot) { if (CurrentScenarioChainEdge.NodeIndexTo != nodeid) { CurrentScenarioChainEdge.NodeIndexTo = nodeid; SetScenarioHasChanged(true); change = true; } } if (change) { UpdateScenarioEdgeLinkage(); //refresh the selected item in the list box, to update the text, and the other controls. ScenarioChainEdgesListBox.Items[ScenarioChainEdgesListBox.SelectedIndex] = ScenarioChainEdgesListBox.SelectedItem; } } private void ScenarioChainEdgeActionComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioChainEdge == null) return; Unk_3609807418 v = (Unk_3609807418)ScenarioChainEdgeActionComboBox.SelectedItem; lock (scenariosyncroot) { if (CurrentScenarioChainEdge.Action != v) { CurrentScenarioChainEdge.Action = v; SetScenarioHasChanged(true); } } } private void ScenarioChainEdgeNavModeComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioChainEdge == null) return; Unk_3971773454 v = (Unk_3971773454)ScenarioChainEdgeNavModeComboBox.SelectedItem; lock (scenariosyncroot) { if (CurrentScenarioChainEdge.NavMode != v) { CurrentScenarioChainEdge.NavMode = v; SetScenarioHasChanged(true); } } } private void ScenarioChainEdgeNavSpeedComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioChainEdge == null) return; Unk_941086046 v = (Unk_941086046)ScenarioChainEdgeNavSpeedComboBox.SelectedItem; lock (scenariosyncroot) { if (CurrentScenarioChainEdge.NavSpeed != v) { CurrentScenarioChainEdge.NavSpeed = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterCheckBox_CheckedChanged(object sender, EventArgs e) { } private void ScenarioClusterAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioClusterDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioCluster(); } private void ScenarioClusterGoToButton_Click(object sender, EventArgs e) { if (CurrentScenarioNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentScenarioNode.Position); } private void ScenarioClusterCenterTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; Vector3 v = FloatUtil.ParseVector3String(ScenarioClusterCenterTextBox.Text); bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.Position != v) { CurrentScenarioNode.SetPosition(v); SetScenarioHasChanged(true); change = true; } if ((CurrentScenarioNode.Cluster != null) && (CurrentScenarioNode.Cluster.Position != v)) { CurrentScenarioNode.Cluster.Position = v; SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioClusterRadiusTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; float r = FloatUtil.Parse(ScenarioClusterRadiusTextBox.Text); bool change = false; lock (scenariosyncroot) { if ((CurrentScenarioNode.Cluster != null) && (CurrentScenarioNode.Cluster.Radius != r)) { CurrentScenarioNode.Cluster.Radius = r; SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioClusterUnk1TextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Cluster == null) return; float v = FloatUtil.Parse(ScenarioClusterUnk1TextBox.Text); lock (scenariosyncroot) { if (CurrentScenarioNode.Cluster.Unk1 != v) { CurrentScenarioNode.Cluster.Unk1 = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterUnk2CheckBox_CheckedChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.Cluster == null) return; bool v = ScenarioClusterUnk2CheckBox.Checked; lock (scenariosyncroot) { if (CurrentScenarioNode.Cluster.Unk2 != v) { CurrentScenarioNode.Cluster.Unk2 = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointsListBox_DoubleClick(object sender, EventArgs e) { var item = ScenarioClusterPointsListBox.SelectedItem as MCScenarioPoint; if (item == null) return; var nodes = CurrentScenario?.ScenarioRegion?.Nodes; if (nodes == null) return; ScenarioNode node = null; foreach (var snode in nodes) { if (snode.ClusterMyPoint == item) { node = snode; break; } } if (node == null) return; TrySelectScenarioNodeTreeNode(node); } private void ScenarioClusterAddPointButton_Click(object sender, EventArgs e) { AddScenarioClusterPoint(); } private void ScenarioClusterPointCheckBox_CheckedChanged(object sender, EventArgs e) { } private void ScenarioClusterPointAddToProjectButton_Click(object sender, EventArgs e) { AddScenarioNodeToProject(); } private void ScenarioClusterPointDeleteButton_Click(object sender, EventArgs e) { DeleteScenarioNode(); } private void ScenarioClusterPointGoToButton_Click(object sender, EventArgs e) { if (CurrentScenarioNode == null) return; if (WorldForm == null) return; WorldForm.GoToPosition(CurrentScenarioNode.Position); } private void ScenarioClusterPointPositionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; Vector3 v = FloatUtil.ParseVector3String(ScenarioClusterPointPositionTextBox.Text); bool change = false; lock (scenariosyncroot) { if (CurrentScenarioNode.Position != v) { CurrentScenarioNode.SetPosition(v); SetScenarioHasChanged(true); change = true; } } if (change) { if (WorldForm != null) { WorldForm.SetWidgetPosition(CurrentScenarioNode.Position); WorldForm.UpdateScenarioGraphics(CurrentScenario, false); } } } private void ScenarioClusterPointDirectionTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; float dir = FloatUtil.Parse(ScenarioClusterPointDirectionTextBox.Text); lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.Direction != dir) { CurrentScenarioNode.ClusterMyPoint.Direction = dir; CurrentScenarioNode.Orientation = CurrentScenarioNode.ClusterMyPoint.Orientation; SetScenarioHasChanged(true); if (WorldForm != null) { WorldForm.SetWidgetRotation(CurrentScenarioNode.Orientation); } } } } private void ScenarioClusterPointTypeComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; ScenarioType stype = ScenarioClusterPointTypeComboBox.SelectedItem as ScenarioType; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.Type != stype) { CurrentScenarioNode.ClusterMyPoint.Type = stype; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); if (CurrentScenarioNode.ChainingNode != null) { ScenarioChainNodeTypeComboBox.SelectedItem = stype; } } private void ScenarioClusterPointModelSetComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; AmbientModelSet mset = ScenarioClusterPointModelSetComboBox.SelectedItem as AmbientModelSet; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.ModelSet != mset) { CurrentScenarioNode.ClusterMyPoint.ModelSet = mset; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioClusterPointInteriorTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; uint hash = 0; string name = ScenarioClusterPointInteriorTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioClusterPointInteriorHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.InteriorName != hash) { CurrentScenarioNode.ClusterMyPoint.InteriorName = hash; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointGroupTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; uint hash = 0; string name = ScenarioClusterPointGroupTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioClusterPointGroupHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.GroupName != hash) { CurrentScenarioNode.ClusterMyPoint.GroupName = hash; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointImapTextBox_TextChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; uint hash = 0; string name = ScenarioClusterPointImapTextBox.Text; if (!uint.TryParse(name, out hash))//don't re-hash hashes { hash = JenkHash.GenHash(name); JenkIndex.Ensure(name); } ScenarioClusterPointImapHashLabel.Text = "Hash: " + hash.ToString(); lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.IMapName != hash) { CurrentScenarioNode.ClusterMyPoint.IMapName = hash; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointTimeStartUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; byte t = (byte)ScenarioClusterPointTimeStartUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.TimeStart != t) { CurrentScenarioNode.ClusterMyPoint.TimeStart = t; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioClusterPointTimeEndUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; byte t = (byte)ScenarioClusterPointTimeEndUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.TimeEnd != t) { CurrentScenarioNode.ClusterMyPoint.TimeEnd = t; SetScenarioHasChanged(true); } } UpdateScenarioNodeTreeNode(CurrentScenarioNode); } private void ScenarioClusterPointProbabilityUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; byte v = (byte)ScenarioClusterPointProbabilityUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.Probability != v) { CurrentScenarioNode.ClusterMyPoint.Probability = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointAnimalFlagUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; byte v = (byte)ScenarioClusterPointAnimalFlagUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.AvailableMpSp != v) { CurrentScenarioNode.ClusterMyPoint.AvailableMpSp = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointRadiusUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; byte v = (byte)ScenarioClusterPointRadiusUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.Radius != v) { CurrentScenarioNode.ClusterMyPoint.Radius = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointWaitTimeUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; byte v = (byte)ScenarioClusterPointWaitTimeUpDown.Value; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.WaitTime != v) { CurrentScenarioNode.ClusterMyPoint.WaitTime = v; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointFlagsUpDown_ValueChanged(object sender, EventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; var iflags = (uint)ScenarioClusterPointFlagsUpDown.Value; populatingui = true; for (int i = 0; i < ScenarioClusterPointFlagsCheckedListBox.Items.Count; i++) { var c = ((iflags & (1 << i)) > 0); ScenarioClusterPointFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); } populatingui = false; Unk_700327466 f = (Unk_700327466)iflags; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.Flags != f) { CurrentScenarioNode.ClusterMyPoint.Flags = f; SetScenarioHasChanged(true); } } } private void ScenarioClusterPointFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { if (populatingui) return; if (CurrentScenarioNode == null) return; if (CurrentScenarioNode.ClusterMyPoint == null) return; uint iflags = 0; for (int i = 0; i < ScenarioClusterPointFlagsCheckedListBox.Items.Count; i++) { if (e.Index == i) { if (e.NewValue == CheckState.Checked) { iflags += (uint)(1 << i); } } else { if (ScenarioClusterPointFlagsCheckedListBox.GetItemChecked(i)) { iflags += (uint)(1 << i); } } } populatingui = true; ScenarioClusterPointFlagsUpDown.Value = iflags; populatingui = false; Unk_700327466 f = (Unk_700327466)iflags; lock (scenariosyncroot) { if (CurrentScenarioNode.ClusterMyPoint.Flags != f) { CurrentScenarioNode.ClusterMyPoint.Flags = f; SetScenarioHasChanged(true); } } } } }