4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Graphics;
7 using System.Collections.Generic;
23 private readonly
GUIFrame leftPanel, rightPanel, bottomPanel, topPanel;
28 private readonly
GUIListBox paramsList, ruinParamsList, caveParamsList, outpostParamsList, levelObjectList;
31 private readonly
GUIButton spriteEditDoneButton;
35 private readonly
GUITickBox lightingEnabled, cursorLightEnabled, allowInvalidOutpost, mirrorLevel;
38 private readonly
GUIDropDown selectedBeaconStationDropdown;
41 private Sprite editingSprite;
45 private readonly Color[] tunnelDebugColors =
new Color[] { Color.White, Color.Cyan, Color.LightGreen, Color.Red, Color.LightYellow, Color.LightSeaGreen };
47 private LevelData currentLevelData;
58 var paddedLeftPanel =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.9f, 0.95f), leftPanel.RectTransform,
Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) })
61 RelativeSpacing = 0.01f
66 PlaySoundOnSelect =
true
72 editorContainer.ClearChildren();
73 SortLevelObjectsList(currentLevelData);
74 new SerializableEntityEditor(editorContainer.Content.RectTransform, selectedParams, inGame:
false, showName:
true, elementHeight: 20, titleFont: GUIStyle.LargeFont);
78 var ruinTitle =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get(
"leveleditor.ruinparams"), font: GUIStyle.SubHeadingFont);
82 PlaySoundOnSelect =
true
90 var caveTitle =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get(
"leveleditor.caveparams"), font: GUIStyle.SubHeadingFont);
94 PlaySoundOnSelect =
true
102 var outpostTitle =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get(
"leveleditor.outpostparams"), font: GUIStyle.SubHeadingFont);
107 PlaySoundOnSelect =
true
115 var createLevelObjButton =
new GUIButton(
new RectTransform(
new Vector2(1.0f, 0.05f), paddedLeftPanel.RectTransform),
116 TextManager.Get(
"leveleditor.createlevelobj"))
118 OnClicked = (btn, obj) =>
120 Wizard.Instance.Create();
127 TextManager.Get(
"leveleditor.lightingenabled"));
129 cursorLightEnabled =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.025f), paddedLeftPanel.RectTransform),
130 TextManager.Get(
"leveleditor.cursorlightenabled"));
133 TextManager.Get(
"leveleditor.reloadtextures"))
135 OnClicked = (btn, obj) =>
143 TextManager.Get(
"editor.saveall"))
145 OnClicked = (btn, obj) =>
148 GUI.AddMessage(TextManager.Get(
"leveleditor.allsaved"), GUIStyle.Green);
154 var paddedRightPanel =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.95f, 0.95f), rightPanel.RectTransform,
Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) })
157 RelativeSpacing = 0.01f
162 var seedContainer =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.04f), paddedRightPanel.RectTransform), isHorizontal:
true, childAnchor:
Anchor.CenterLeft);
163 Vector2 randomizeButtonRelativeSize = GetRandomizeButtonRelativeSize();
164 Vector2 elementRelativeSize = GetSeedElementRelativeSize();
165 var seedLabel =
new GUITextBlock(
new RectTransform(elementRelativeSize, seedContainer.RectTransform), TextManager.Get(
"leveleditor.levelseed"));
167 var seedButton =
new GUIButton(
new RectTransform(randomizeButtonRelativeSize, seedContainer.RectTransform), style:
"RandomizeButton")
169 OnClicked = (button, userData) =>
171 if (seedBox ==
null) {
return false; }
172 seedBox.
Text = GetLevelSeed();
176 seedContainer.RectTransform.SizeChanged += () =>
178 Vector2 randomizeButtonRelativeSize = GetRandomizeButtonRelativeSize();
179 Vector2 elementRelativeSize = GetSeedElementRelativeSize();
180 seedLabel.RectTransform.RelativeSize = elementRelativeSize;
181 seedBox.RectTransform.RelativeSize = elementRelativeSize;
182 seedButton.RectTransform.RelativeSize = randomizeButtonRelativeSize;
184 Vector2 GetRandomizeButtonRelativeSize() => 0.2f * seedContainer.Rect.Width > seedContainer.Rect.Height ?
185 new Vector2(Math.Min((
float)seedContainer.Rect.Height / seedContainer.Rect.Width, 0.2f), 1.0f) :
186 new Vector2(0.15f, Math.Min((0.2f * seedContainer.Rect.Width) / seedContainer.Rect.Height, 1.0f));
187 Vector2 GetSeedElementRelativeSize() =>
new Vector2(0.5f * (1.0f - randomizeButtonRelativeSize.X), 1.0f);
188 static string GetLevelSeed() => ToolBox.RandomSeed(8);
190 var subDropDownContainer =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), isHorizontal:
true);
191 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1.0f), subDropDownContainer.RectTransform), TextManager.Get(
"submarine"));
192 selectedSubDropDown =
new GUIDropDown(
new RectTransform(
new Vector2(0.5f, 1.0f), subDropDownContainer.RectTransform));
196 selectedSubDropDown.AddItem(sub.
DisplayName, userData: sub);
198 subDropDownContainer.RectTransform.MinSize =
new Point(0, selectedSubDropDown.RectTransform.MinSize.Y);
200 var beaconStationDropDownContainer =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), isHorizontal:
true);
201 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1.0f), beaconStationDropDownContainer.RectTransform), TextManager.Get(
"submarinetype.beaconstation"));
202 selectedBeaconStationDropdown =
new GUIDropDown(
new RectTransform(
new Vector2(0.5f, 1.0f), beaconStationDropDownContainer.RectTransform));
203 selectedBeaconStationDropdown.AddItem(TextManager.Get(
"Any"), userData:
null);
207 selectedBeaconStationDropdown.AddItem(beaconStation.
DisplayName, userData: beaconStation);
209 beaconStationDropDownContainer.RectTransform.MinSize =
new Point(0, selectedBeaconStationDropdown.RectTransform.MinSize.Y);
211 var wreckDropDownContainer =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), isHorizontal:
true);
212 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1.0f), wreckDropDownContainer.RectTransform), TextManager.Get(
"submarinetype.wreck"));
213 selectedWreckDropdown =
new GUIDropDown(
new RectTransform(
new Vector2(0.5f, 1.0f), wreckDropDownContainer.RectTransform));
214 selectedWreckDropdown.AddItem(TextManager.Get(
"Any"), userData:
null);
218 selectedWreckDropdown.AddItem(wreck.
DisplayName, userData: wreck);
220 wreckDropDownContainer.RectTransform.MinSize =
new Point(0, selectedWreckDropdown.RectTransform.MinSize.Y);
222 mirrorLevel =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), TextManager.Get(
"mirrorentityx"));
224 allowInvalidOutpost =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.025f), paddedRightPanel.RectTransform),
225 TextManager.Get(
"leveleditor.allowinvalidoutpost"))
227 ToolTip = TextManager.Get(
"leveleditor.allowinvalidoutpost.tooltip")
231 TextManager.Get(
"leveleditor.generate"))
233 OnClicked = (btn, obj) =>
238 if (selectedSubDropDown.SelectedData is
SubmarineInfo subInfo)
245 currentLevelData.ForceBeaconStation = selectedBeaconStationDropdown.SelectedData as
SubmarineInfo;
246 currentLevelData.ForceWreck = selectedWreckDropdown.SelectedData as
SubmarineInfo;
247 currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
249 Level.
Generate(currentLevelData, mirror: mirrorLevel.Selected, startLocation: dummyLocations[0], endLocation: dummyLocations[1]);
277 TextManager.Get(
"leveleditor.test"))
279 OnClicked = (btn, obj) =>
289 foreach (
Entity ent
in toRemove)
296 var nonPlayerFiles = ContentPackageManager.EnabledPackages.All.SelectMany(p => p
297 .GetFiles<BaseSubFile>()
302 !nonPlayerFiles.Any(f => f.Path == s.FilePath));
310 var toRemove =
Entity.
GetEntities().Where(e => !currEntities.Contains(e)).ToList();
311 foreach (
Entity ent
in toRemove)
326 { MaxSize = new Point(GameMain.GraphicsWidth - rightPanel.Rect.Width, 1000) }, style:
"GUIFrameBottom");
330 PlaySoundOnSelect =
true,
336 CreateLevelObjectEditor(selectedLevelObject);
340 spriteEditDoneButton =
new GUIButton(
new RectTransform(
new Point(200, 30), anchor:
Anchor.BottomRight) { AbsoluteOffset = new Point(20, 20) },
341 TextManager.Get(
"leveleditor.spriteeditdone"))
343 OnClicked = (btn, userdata) =>
345 editingSprite =
null;
351 { RelativeOffset = new Vector2(leftPanel.RectTransform.RelativeSize.X * 2, 0.0f) }, style:
"GUIFrameTop");
356 CoroutineManager.StartCoroutine(GenerateLevels());
358 IEnumerable<CoroutineStatus> GenerateLevels()
360 using var errorCatcher = DebugConsole.ErrorCatcher.Create();
361 for (
int i = 0; i < amountOfLevelsToGenerate; i++)
368 currentLevelData.ForceBeaconStation = selectedBeaconStationDropdown.SelectedData as
SubmarineInfo;
369 currentLevelData.ForceWreck = selectedWreckDropdown.SelectedData as
SubmarineInfo;
371 currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
373 DebugConsole.NewMessage(
"*****************************************************************************");
374 DebugConsole.NewMessage($
"Generating level {(i + 1)}/{amountOfLevelsToGenerate}: ");
375 DebugConsole.NewMessage(
" Seed: " + currentLevelData.Seed);
376 DebugConsole.NewMessage(
" Outpost parameters: " + (currentLevelData.ForceOutpostGenerationParams?.Name ??
"None"));
377 DebugConsole.NewMessage(
" Level generation params: " + selectedParams.Identifier);
378 DebugConsole.NewMessage(
" Mirrored: " + mirrorLevel.Selected);
379 DebugConsole.NewMessage(
" Adjacent locations: " + (dummyLocations[0]?.Type.Identifier ??
"none".ToIdentifier()) +
", " + (dummyLocations[1]?.Type.Identifier ??
"none".ToIdentifier()));
383 Level.
Generate(currentLevelData, mirror: mirrorLevel.Selected, startLocation: dummyLocations[0], endLocation: dummyLocations[1]);
388 if (errorCatcher.Errors.Any())
390 DebugConsole.ThrowError(
"Error while generating level:");
391 errorCatcher.Errors.ToList().ForEach(e => DebugConsole.ThrowError(e.Text));
407 GUI.PreventPauseMenuToggle =
false;
408 pointerLightSource =
new LightSource(Vector2.Zero, 1000.0f, Color.White, submarine:
null);
410 topPanel.ClearChildren();
413 editingSprite =
null;
415 UpdateRuinParamsList();
416 UpdateCaveParamsList();
417 UpdateOutpostParamsList();
418 UpdateLevelObjectsList();
423 pointerLightSource?.
Remove();
424 pointerLightSource =
null;
427 private void UpdateParamsList()
429 editorContainer.ClearChildren();
430 paramsList.Content.ClearChildren();
434 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), paramsList.Content.RectTransform) { MinSize = new Point(0, 20) },
437 Padding = Vector4.Zero,
443 private void UpdateCaveParamsList()
445 editorContainer.ClearChildren();
446 caveParamsList.Content.ClearChildren();
448 foreach (CaveGenerationParams genParams
in CaveGenerationParams.CaveParams.OrderBy(p => p.Name))
450 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), caveParamsList.Content.RectTransform) { MinSize = new Point(0, 20) },
453 Padding = Vector4.Zero,
459 private void UpdateRuinParamsList()
461 editorContainer.ClearChildren();
462 ruinParamsList.Content.ClearChildren();
466 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), ruinParamsList.Content.RectTransform) { MinSize = new Point(0, 20) },
469 Padding = Vector4.Zero,
475 private void UpdateOutpostParamsList()
477 editorContainer.ClearChildren();
478 outpostParamsList.Content.ClearChildren();
480 foreach (OutpostGenerationParams genParams
in OutpostGenerationParams.OutpostParams.OrderBy(p => p.Name))
482 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), outpostParamsList.Content.RectTransform) { MinSize = new Point(0, 20) },
485 Padding = Vector4.Zero,
491 private void UpdateLevelObjectsList()
493 editorContainer.ClearChildren();
494 levelObjectList.Content.ClearChildren();
496 int objectsPerRow = (int)Math.Ceiling(levelObjectList.Content.Rect.Width / Math.Max(100 * GUI.Scale, 100));
497 float relWidth = 1.0f / objectsPerRow;
499 foreach (LevelObjectPrefab levelObjPrefab
in LevelObjectPrefab.Prefabs)
501 var frame =
new GUIFrame(
new RectTransform(
502 new Vector2(relWidth, relWidth * ((
float)levelObjectList.Content.Rect.Width / levelObjectList.Content.Rect.Height)),
503 levelObjectList.Content.RectTransform) { MinSize = new Point(0, 60) }, style:
"ListBoxElementSquare")
505 UserData = levelObjPrefab
507 var paddedFrame =
new GUIFrame(
new RectTransform(
new Vector2(0.9f, 0.9f), frame.RectTransform,
Anchor.Center), style:
null);
509 GUITextBlock textBlock =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), paddedFrame.RectTransform,
Anchor.BottomCenter),
510 text: ToolBox.LimitString(levelObjPrefab.Name, GUIStyle.SmallFont, paddedFrame.Rect.Width), textAlignment: Alignment.Center, font: GUIStyle.SmallFont)
512 CanBeFocused =
false,
513 ToolTip = levelObjPrefab.Name
516 Sprite sprite = levelObjPrefab.Sprites.FirstOrDefault() ?? levelObjPrefab.DeformableSprite?.Sprite;
517 new GUIImage(
new RectTransform(
new Point(paddedFrame.Rect.Height, paddedFrame.Rect.Height - textBlock.Rect.Height),
518 paddedFrame.RectTransform,
Anchor.TopCenter), sprite, scaleToFit:
true)
520 LoadAsynchronously =
true,
526 private void CreateCaveParamsEditor(CaveGenerationParams caveGenerationParams)
528 editorContainer.ClearChildren();
529 var editor =
new SerializableEntityEditor(editorContainer.Content.RectTransform, caveGenerationParams,
false,
true, elementHeight: 20);
531 if (selectedParams !=
null)
533 var commonnessContainer =
new GUILayoutGroup(
new RectTransform(
new Point(editor.Rect.Width, 70)) { IsFixedSize = true },
534 isHorizontal:
false, childAnchor:
Anchor.TopCenter)
539 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.4f), commonnessContainer.RectTransform),
540 TextManager.GetWithVariable(
"leveleditor.levelobjcommonness",
"[leveltype]", selectedParams.
Identifier.Value), textAlignment: Alignment.Center);
541 new GUINumberInput(
new RectTransform(
new Vector2(0.5f, 0.4f), commonnessContainer.RectTransform),
NumberType.Float)
545 FloatValue = caveGenerationParams.GetCommonness(currentLevelData, abyss:
false),
546 OnValueChanged = (numberInput) =>
548 caveGenerationParams.OverrideCommonness[selectedParams.
Identifier] = numberInput.FloatValue;
551 new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style:
null);
552 editor.AddCustomContent(commonnessContainer, 1);
556 private void CreateOutpostGenerationParamsEditor(OutpostGenerationParams outpostGenerationParams)
558 editorContainer.ClearChildren();
559 var outpostParamsEditor =
new SerializableEntityEditor(editorContainer.Content.RectTransform, outpostGenerationParams,
false,
true, elementHeight: 20);
563 var locationTypeGroup =
new GUILayoutGroup(
new RectTransform(
new Point(editorContainer.Content.Rect.Width, 20)), isHorizontal:
true, childAnchor:
Anchor.CenterLeft)
568 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), locationTypeGroup.RectTransform), TextManager.Get(
"outpostmoduleallowedlocationtypes"), textAlignment: Alignment.CenterLeft);
569 HashSet<Identifier> availableLocationTypes =
new HashSet<Identifier> {
"any".ToIdentifier() };
570 foreach (LocationType locationType
in LocationType.Prefabs) { availableLocationTypes.Add(locationType.Identifier); }
572 var locationTypeDropDown =
new GUIDropDown(
new RectTransform(
new Vector2(0.5f, 1f), locationTypeGroup.RectTransform),
573 text: LocalizedString.Join(
", ", outpostGenerationParams.AllowedLocationTypes.Select(lt => TextManager.Capitalize(lt.Value)) ?? ((LocalizedString)
"any").ToEnumerable()), selectMultiple:
true);
574 foreach (Identifier locationType
in availableLocationTypes)
576 locationTypeDropDown.AddItem(TextManager.Capitalize(locationType.Value), locationType);
577 if (outpostGenerationParams.AllowedLocationTypes.Contains(locationType))
579 locationTypeDropDown.SelectItem(locationType);
582 if (!outpostGenerationParams.AllowedLocationTypes.Any())
584 locationTypeDropDown.SelectItem(
"any");
587 locationTypeDropDown.OnSelected += (_, __) =>
589 outpostGenerationParams.SetAllowedLocationTypes(locationTypeDropDown.SelectedDataMultiple.Cast<Identifier>());
590 locationTypeDropDown.Text = ToolBox.LimitString(locationTypeDropDown.Text, locationTypeDropDown.Font, locationTypeDropDown.Rect.Width);
593 locationTypeGroup.RectTransform.MinSize =
new Point(locationTypeGroup.Rect.Width, locationTypeGroup.RectTransform.Children.Max(c => c.MinSize.Y));
595 outpostParamsEditor.AddCustomContent(locationTypeGroup, 100);
599 var moduleLabel =
new GUITextBlock(
new RectTransform(
new Point(editorContainer.Content.Rect.Width, (
int)(70 * GUI.Scale))), TextManager.Get(
"submarinetype.outpostmodules"), font: GUIStyle.SubHeadingFont);
600 outpostParamsEditor.AddCustomContent(moduleLabel, 100);
602 foreach (var moduleCount
in outpostGenerationParams.ModuleCounts)
604 var moduleCountGroup =
new GUILayoutGroup(
new RectTransform(
new Point(editorContainer.Content.Rect.Width, (
int)(25 * GUI.Scale))), isHorizontal:
true, childAnchor:
Anchor.CenterLeft);
605 new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1f), moduleCountGroup.RectTransform), TextManager.Capitalize(moduleCount.Identifier.Value), textAlignment: Alignment.CenterLeft);
606 new GUINumberInput(
new RectTransform(
new Vector2(0.5f, 1f), moduleCountGroup.RectTransform),
NumberType.Int)
610 IntValue = moduleCount.Count,
611 OnValueChanged = (numInput) =>
613 outpostGenerationParams.SetModuleCount(moduleCount.Identifier, numInput.IntValue);
614 if (numInput.IntValue == 0)
616 outpostParamsList.Select(outpostParamsList.SelectedData);
620 moduleCountGroup.RectTransform.MinSize =
new Point(moduleCountGroup.Rect.Width, moduleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y));
621 outpostParamsEditor.AddCustomContent(moduleCountGroup, 100);
626 var addModuleCountGroup =
new GUILayoutGroup(
new RectTransform(
new Point(editorContainer.Content.Rect.Width, (
int)(40 * GUI.Scale))), isHorizontal:
true, childAnchor:
Anchor.Center);
628 HashSet<Identifier> availableFlags =
new HashSet<Identifier>();
629 foreach (Identifier flag
in OutpostGenerationParams.OutpostParams.SelectMany(p => p.ModuleCounts.Select(m => m.Identifier))) { availableFlags.Add(flag); }
630 foreach (var sub
in SubmarineInfo.SavedSubmarines)
632 if (sub.OutpostModuleInfo ==
null) {
continue; }
633 foreach (Identifier flag
in sub.OutpostModuleInfo.ModuleFlags) { availableFlags.Add(flag); }
636 var moduleTypeDropDown =
new GUIDropDown(
new RectTransform(
new Vector2(0.8f, 0.8f), addModuleCountGroup.RectTransform),
637 text: TextManager.Get(
"leveleditor.addmoduletype"));
638 foreach (Identifier flag
in availableFlags)
640 if (outpostGenerationParams.ModuleCounts.Any(mc => mc.Identifier == flag)) {
continue; }
641 moduleTypeDropDown.AddItem(TextManager.Capitalize(flag.Value), flag);
643 moduleTypeDropDown.OnSelected += (_, userdata) =>
645 outpostGenerationParams.SetModuleCount((Identifier)userdata, 1);
646 outpostParamsList.Select(outpostParamsList.SelectedData);
649 addModuleCountGroup.RectTransform.MinSize =
new Point(addModuleCountGroup.Rect.Width, addModuleCountGroup.RectTransform.Children.Max(c => c.MinSize.Y));
650 outpostParamsEditor.AddCustomContent(addModuleCountGroup, 100);
654 private void CreateLevelObjectEditor(LevelObjectPrefab levelObjectPrefab)
656 editorContainer.ClearChildren();
658 var editor =
new SerializableEntityEditor(editorContainer.Content.RectTransform, levelObjectPrefab,
false,
true, elementHeight: 20, titleFont: GUIStyle.LargeFont);
660 if (selectedParams !=
null)
662 List<Identifier> availableIdentifiers =
new List<Identifier>();
663 if (selectedParams !=
null) { availableIdentifiers.Add(selectedParams.
Identifier); }
664 foreach (var caveParam
in CaveGenerationParams.CaveParams)
666 if (selectedParams !=
null && caveParam.GetCommonness(currentLevelData, abyss:
false) <= 0.0f) {
continue; }
667 availableIdentifiers.Add(caveParam.Identifier);
669 availableIdentifiers.Reverse();
671 foreach (Identifier paramsId
in availableIdentifiers)
673 var commonnessContainer =
new GUILayoutGroup(
new RectTransform(
new Point(editor.Rect.Width, 70)) { IsFixedSize = true },
674 isHorizontal:
false, childAnchor:
Anchor.TopCenter)
679 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.4f), commonnessContainer.RectTransform),
680 TextManager.GetWithVariable(
"leveleditor.levelobjcommonness",
"[leveltype]", paramsId.Value), textAlignment: Alignment.Center);
681 new GUINumberInput(
new RectTransform(
new Vector2(0.5f, 0.4f), commonnessContainer.RectTransform),
NumberType.Float)
685 FloatValue = selectedParams.
Identifier == paramsId ? levelObjectPrefab.GetCommonness(currentLevelData) : levelObjectPrefab.GetCommonness(CaveGenerationParams.CaveParams.Find(p => p.Identifier == paramsId)),
686 OnValueChanged = (numberInput) =>
688 levelObjectPrefab.OverrideCommonness[paramsId] = numberInput.FloatValue;
691 new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.2f), commonnessContainer.RectTransform), style:
null);
692 editor.AddCustomContent(commonnessContainer, 1);
696 Sprite sprite = levelObjectPrefab.Sprites.FirstOrDefault() ?? levelObjectPrefab.DeformableSprite?.Sprite;
699 editor.AddCustomContent(
new GUIButton(
new RectTransform(
new Point(editor.Rect.Width / 2, (
int)(25 * GUI.Scale))) { IsFixedSize = true },
700 TextManager.Get(
"leveleditor.editsprite"))
702 OnClicked = (btn, userdata) =>
704 editingSprite = sprite;
705 GameMain.SpriteEditorScreen.SelectSprite(editingSprite);
711 if (levelObjectPrefab.DeformableSprite !=
null)
713 var deformEditor = levelObjectPrefab.DeformableSprite.CreateEditor(editor, levelObjectPrefab.SpriteDeformations, levelObjectPrefab.Name);
714 deformEditor.GetChild<GUIDropDown>().OnSelected += (selected, userdata) =>
716 CreateLevelObjectEditor(selectedLevelObject);
719 editor.AddCustomContent(deformEditor, editor.ContentCount);
722 new GUITextBlock(
new RectTransform(
new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform),
723 TextManager.Get(
"leveleditor.childobjects"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomCenter);
724 foreach (LevelObjectPrefab.ChildObject childObj in levelObjectPrefab.ChildObjects)
726 var childObjFrame =
new GUIFrame(
new RectTransform(
new Point(editor.Rect.Width, 30)));
727 var paddedFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.95f, 0.9f), childObjFrame.RectTransform,
Anchor.Center), isHorizontal:
true)
730 RelativeSpacing = 0.05f
732 var selectedChildObj = childObj;
733 var dropdown =
new GUIDropDown(
new RectTransform(
new Vector2(0.5f, 1.0f), paddedFrame.RectTransform), elementCount: 10, selectMultiple:
true);
734 foreach (LevelObjectPrefab objPrefab
in LevelObjectPrefab.Prefabs)
736 dropdown.AddItem(objPrefab.Name, objPrefab);
737 if (childObj.AllowedNames.Contains(objPrefab.Name)) { dropdown.SelectItem(objPrefab); }
739 dropdown.OnSelected = (selected, obj) =>
741 childObj.AllowedNames = dropdown.SelectedDataMultiple.Select(d => ((LevelObjectPrefab)d).Name).ToList();
744 new GUINumberInput(
new RectTransform(
new Vector2(0.2f, 1.0f), paddedFrame.RectTransform),
NumberType.Int)
748 OnValueChanged = (numberInput) =>
750 selectedChildObj.MinCount = numberInput.IntValue;
751 selectedChildObj.MaxCount = Math.Max(selectedChildObj.MaxCount, selectedChildObj.MinCount);
753 }.IntValue = childObj.MinCount;
754 new GUINumberInput(
new RectTransform(
new Vector2(0.2f, 1.0f), paddedFrame.RectTransform),
NumberType.Int)
758 OnValueChanged = (numberInput) =>
760 selectedChildObj.MaxCount = numberInput.IntValue;
761 selectedChildObj.MinCount = Math.Min(selectedChildObj.MaxCount, selectedChildObj.MinCount);
763 }.IntValue = childObj.MaxCount;
765 new GUIButton(
new RectTransform(
new Vector2(0.1f, 1.0f), paddedFrame.RectTransform, scaleBasis:
ScaleBasis.BothHeight), style:
"GUICancelButton")
767 OnClicked = (btn, userdata) =>
769 selectedLevelObject.
ChildObjects.Remove(selectedChildObj);
770 CreateLevelObjectEditor(selectedLevelObject);
775 childObjFrame.RectTransform.Parent = editorContainer.Content.RectTransform;
778 var buttonContainer =
new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.01f), editorContainer.Content.RectTransform), style:
null);
779 new GUIButton(
new RectTransform(
new Point(editor.Rect.Width / 2, 20), buttonContainer.RectTransform,
Anchor.Center),
780 TextManager.Get(
"leveleditor.addchildobject"))
782 OnClicked = (btn, userdata) =>
784 selectedLevelObject.
ChildObjects.Add(
new LevelObjectPrefab.ChildObject());
785 CreateLevelObjectEditor(selectedLevelObject);
789 buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.Children.First().MinSize;
792 new GUITextBlock(
new RectTransform(
new Point(editor.Rect.Width, 40), editorContainer.Content.RectTransform),
793 TextManager.Get(
"leveleditor.lightsources"), textAlignment: Alignment.BottomCenter, font: GUIStyle.SubHeadingFont);
796 new SerializableEntityEditor(editorContainer.Content.RectTransform, lightSourceParams, inGame:
false, showName:
true);
798 buttonContainer =
new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.01f), editorContainer.Content.RectTransform), style:
null);
799 new GUIButton(
new RectTransform(
new Point(editor.Rect.Width / 2, 20), buttonContainer.RectTransform,
Anchor.Center),
800 TextManager.Get(
"leveleditor.addlightsource"))
802 OnClicked = (btn, userdata) =>
806 CreateLevelObjectEditor(selectedLevelObject);
810 buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.Children.First().MinSize;
813 private void SortLevelObjectsList(LevelData levelData)
816 foreach (GUIComponent levelObjFrame
in levelObjectList.Content.Children)
818 var levelObj = levelObjFrame.UserData as LevelObjectPrefab;
819 float commonness = levelObj.GetCommonness(levelData);
820 levelObjFrame.Color = commonness > 0.0f ? GUIStyle.Green * 0.4f : Color.Transparent;
821 levelObjFrame.SelectedColor = commonness > 0.0f ? GUIStyle.Green * 0.6f : Color.White * 0.5f;
822 levelObjFrame.HoverColor = commonness > 0.0f ? GUIStyle.Green * 0.7f : Color.White * 0.6f;
824 levelObjFrame.GetAnyChild<GUIImage>().Color = commonness > 0.0f ? Color.White : Color.DarkGray;
825 if (commonness <= 0.0f)
827 levelObjFrame.GetAnyChild<GUITextBlock>().TextColor = Color.DarkGray;
832 levelObjectList.Content.RectTransform.SortChildren((c1, c2) =>
834 var levelObj1 = c1.GUIComponent.UserData as LevelObjectPrefab;
835 var levelObj2 = c2.GUIComponent.UserData as LevelObjectPrefab;
836 return Math.Sign(levelObj2.GetCommonness(levelData) - levelObj1.GetCommonness(levelData));
842 base.AddToGUIUpdateList();
843 rightPanel.Visible = leftPanel.Visible = bottomPanel.Visible = editingSprite ==
null;
844 if (editingSprite !=
null)
847 spriteEditDoneButton.AddToGUIUpdateList();
849 else if (lightingEnabled.Selected && cursorLightEnabled.Selected)
851 topPanel.AddToGUIUpdateList();
855 public override void Draw(
double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
857 if (lightingEnabled.Selected)
861 graphics.Clear(Color.Black);
867 spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, SamplerState.LinearWrap, DepthStencilState.DepthRead, transformMatrix: Cam.Transform);
877 Color tunnelColor = tunnelDebugColors[i % tunnelDebugColors.Length] * 0.2f;
878 for (
int j = 1; j < tunnel.Nodes.Count; j++)
880 Vector2 start =
new Vector2(tunnel.Nodes[j - 1].X, -tunnel.Nodes[j - 1].Y);
881 Vector2 end =
new Vector2(tunnel.Nodes[j].X, -tunnel.Nodes[j].Y);
882 GUI.DrawLine(spriteBatch, start, end, tunnelColor, width: (
int)(2.0f / Cam.Zoom));
888 if (interestingPos.Position.X < Cam.WorldView.X || interestingPos.Position.X > Cam.WorldView.Right ||
889 interestingPos.Position.Y > Cam.WorldView.Y || interestingPos.Position.Y < Cam.WorldView.Y - Cam.WorldView.Height)
894 Vector2 pos =
new Vector2(interestingPos.Position.X, -interestingPos.Position.Y);
895 spriteBatch.DrawCircle(pos, 500, 6, Color.White * 0.5f, thickness: (
int)(2 / Cam.Zoom));
896 GUI.DrawString(spriteBatch, pos, interestingPos.PositionType.ToString(), Color.White, font: GUIStyle.LargeFont);
902 Vector2 pathPointPos =
new Vector2(pathPoint.Position.X, -pathPoint.Position.Y);
903 foreach (var location
in pathPoint.ClusterLocations)
905 if (location.Resources ==
null) {
continue; }
906 foreach (var resource
in location.Resources)
908 Vector2 resourcePos =
new Vector2(resource.Position.X, -resource.Position.Y);
909 spriteBatch.DrawCircle(resourcePos, 100, 6, Color.DarkGreen * 0.5f, thickness: (
int)(2 / Cam.Zoom));
910 GUI.DrawString(spriteBatch, resourcePos, resource.Name, Color.DarkGreen, font: GUIStyle.LargeFont);
911 var dist = Vector2.Distance(resourcePos, pathPointPos);
912 var lineStartPos = Vector2.Lerp(resourcePos, pathPointPos, 110 / dist);
913 var lineEndPos = Vector2.Lerp(pathPointPos, resourcePos, 310 / dist);
914 GUI.DrawLine(spriteBatch, lineStartPos, lineEndPos, Color.DarkGreen * 0.5f, width: (
int)(2 / Cam.Zoom));
917 var color = pathPoint.ShouldContainResources ? Color.DarkGreen : Color.DarkRed;
918 spriteBatch.DrawCircle(pathPointPos, 300, 6, color * 0.5f, thickness: (
int)(2 / Cam.Zoom));
919 GUI.DrawString(spriteBatch, pathPointPos,
"Path Point\n" + pathPoint.Id, color, font: GUIStyle.LargeFont);
924 if (location.Resources ==
null) {
continue; }
925 foreach (var resource
in location.Resources)
927 Vector2 resourcePos =
new Vector2(resource.Position.X, -resource.Position.Y);
928 spriteBatch.DrawCircle(resourcePos, 100, 6, Color.DarkGreen * 0.5f, thickness: (
int)(2 / Cam.Zoom));
929 GUI.DrawString(spriteBatch, resourcePos, resource.Name, Color.DarkGreen, font: GUIStyle.LargeFont);
952 if (lightingEnabled.Selected)
954 spriteBatch.Begin(SpriteSortMode.Immediate, Lights.CustomBlendStates.Multiplicative,
null, DepthStencilState.None,
null,
null,
null);
960 if (editingSprite !=
null)
971 GUI.DrawLine(spriteBatch,
new Vector2(0, crushDepthScreen),
new Vector2(
GameMain.
GraphicsWidth, crushDepthScreen), GUIStyle.Red * 0.25f, width: 5);
972 GUI.DrawString(spriteBatch,
new Vector2(
GameMain.
GraphicsWidth / 2, crushDepthScreen),
"Crush depth", GUIStyle.Red, backgroundColor: Color.Black);
978 GUI.DrawLine(spriteBatch,
new Vector2(0, abyssStartScreen),
new Vector2(
GameMain.
GraphicsWidth, abyssStartScreen), GUIStyle.Blue * 0.25f, width: 5);
979 GUI.DrawString(spriteBatch,
new Vector2(
GameMain.
GraphicsWidth / 2, abyssStartScreen),
"Abyss start", GUIStyle.Blue, backgroundColor: Color.Black);
984 GUI.DrawLine(spriteBatch,
new Vector2(0, abyssEndScreen),
new Vector2(
GameMain.
GraphicsWidth, abyssEndScreen), GUIStyle.Blue * 0.25f, width: 5);
985 GUI.DrawString(spriteBatch,
new Vector2(
GameMain.
GraphicsWidth / 2, abyssEndScreen),
"Abyss end", GUIStyle.Blue, backgroundColor: Color.Black);
988 GUI.Draw(Cam, spriteBatch);
993 public override void Update(
double deltaTime)
995 if (lightingEnabled.Selected)
999 if (item ==
null || item.
IsHidden) {
continue; }
1000 foreach (var light
in item.GetComponents<Items.
Components.LightComponent>())
1002 light.Update((
float)deltaTime, Cam);
1009 pointerLightSource.
Enabled = cursorLightEnabled.Selected;
1011 Cam.MoveCamera((
float)deltaTime, allowZoom: GUI.MouseOn ==
null);
1012 Cam.UpdateTransform();
1015 if (editingSprite !=
null)
1021 private void SerializeAll()
1023 IEnumerable<ContentPackage> packages = ContentPackageManager.LocalPackages;
1025 packages = packages.Union(ContentPackageManager.VanillaCorePackage.ToEnumerable());
1028 System.Xml.XmlWriterSettings settings =
new System.Xml.XmlWriterSettings
1031 NewLineOnAttributes =
true
1033 foreach (var configFile
in packages.SelectMany(p => p.GetFiles<LevelGenerationParametersFile>()))
1035 XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
1036 if (doc ==
null) {
continue; }
1038 foreach (LevelGenerationParams genParams
in LevelGenerationParams.LevelParams)
1040 foreach (XElement element
in doc.Root.Elements())
1042 if (element.IsOverride())
1044 foreach (var subElement
in element.Elements())
1046 string id = element.GetAttributeString(
"identifier",
null) ?? element.Name.ToString();
1047 if (!
id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) {
continue; }
1048 SerializableProperty.SerializeProperties(genParams, element,
true);
1053 string id = element.GetAttributeString(
"identifier",
null) ?? element.Name.ToString();
1054 if (!
id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) {
continue; }
1055 SerializableProperty.SerializeProperties(genParams, element,
true);
1060 using (var writer =
XmlWriter.
Create(configFile.Path.Value, settings))
1062 doc.WriteTo(writer);
1067 foreach (var configFile
in packages.SelectMany(p => p.GetFiles<CaveGenerationParametersFile>()))
1069 XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
1070 if (doc ==
null) {
continue; }
1072 foreach (CaveGenerationParams genParams
in CaveGenerationParams.CaveParams)
1074 foreach (XElement element
in doc.Root.Elements())
1076 if (element.IsOverride())
1078 foreach (var subElement
in element.Elements())
1080 string id = subElement.GetAttributeString(
"identifier",
null) ?? subElement.Name.ToString();
1081 if (!
id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) {
continue; }
1082 genParams.Save(subElement);
1087 string id = element.GetAttributeString(
"identifier",
null) ?? element.Name.ToString();
1088 if (!
id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) {
continue; }
1089 genParams.Save(element);
1094 using (var writer =
XmlWriter.
Create(configFile.Path.Value, settings))
1096 doc.WriteTo(writer);
1101 settings.NewLineOnAttributes =
false;
1102 foreach (var configFile
in packages.SelectMany(p => p.GetFiles<LevelObjectPrefabsFile>()))
1104 XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
1105 if (doc ==
null) {
continue; }
1107 foreach (LevelObjectPrefab levelObjPrefab
in LevelObjectPrefab.Prefabs)
1109 foreach (XElement element
in doc.Root.Elements())
1111 Identifier identifier = element.GetAttributeIdentifier(
"identifier",
"");
1112 if (identifier != levelObjPrefab.Identifier) {
continue; }
1113 levelObjPrefab.Save(element);
1117 using (var writer =
XmlWriter.
Create(configFile.Path.Value, settings))
1119 doc.WriteTo(writer);
1127 private void Serialize(LevelGenerationParams genParams)
1129 foreach (var configFile
in ContentPackageManager.AllPackages.SelectMany(p => p.GetFiles<LevelGenerationParametersFile>()))
1131 XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
1132 if (doc ==
null) {
continue; }
1134 bool elementFound =
false;
1135 foreach (XElement element
in doc.Root.Elements())
1137 string id = element.GetAttributeString(
"identifier",
null) ?? element.Name.ToString();
1138 if (!
id.Equals(genParams.Name, StringComparison.OrdinalIgnoreCase)) {
continue; }
1139 SerializableProperty.SerializeProperties(genParams, element,
true);
1140 elementFound =
true;
1145 System.Xml.XmlWriterSettings settings =
new System.Xml.XmlWriterSettings
1148 NewLineOnAttributes =
true
1151 using (var writer =
XmlWriter.
Create(configFile.Path.Value, settings))
1153 doc.WriteTo(writer);
1162 #region LevelObject Wizard
1163 private class Wizard
1165 private LevelObjectPrefab newPrefab;
1167 private static Wizard instance;
1168 public static Wizard Instance
1172 if (instance ==
null)
1174 instance =
new Wizard();
1180 public void AddToGUIUpdateList()
1185 public GUIMessageBox Create()
1187 var box =
new GUIMessageBox(TextManager.Get(
"leveleditor.createlevelobj"),
string.Empty,
1188 new LocalizedString[] { TextManager.Get(
"cancel"), TextManager.Get(
"done") },
new Vector2(0.5f, 0.8f));
1190 box.Content.ChildAnchor =
Anchor.TopCenter;
1191 box.Content.AbsoluteSpacing = 20;
1192 int elementSize = 30;
1193 var listBox =
new GUIListBox(
new RectTransform(
new Vector2(1, 0.75f), box.Content.RectTransform));
1195 new GUITextBlock(
new RectTransform(
new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform),
1196 TextManager.Get(
"leveleditor.levelobjname")) { CanBeFocused =
false };
1197 var nameBox =
new GUITextBox(
new RectTransform(
new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform));
1199 new GUITextBlock(
new RectTransform(
new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform),
1200 TextManager.Get(
"leveleditor.levelobjtexturepath")) { CanBeFocused =
false };
1201 var texturePathBox =
new GUITextBox(
new RectTransform(
new Point(listBox.Content.Rect.Width, elementSize), listBox.Content.RectTransform));
1202 foreach (LevelObjectPrefab prefab
in LevelObjectPrefab.Prefabs)
1204 if (prefab.Sprites.FirstOrDefault() ==
null) {
continue; }
1205 texturePathBox.Text = Path.GetDirectoryName(prefab.Sprites.FirstOrDefault().FilePath.Value);
1210 newPrefab =
new LevelObjectPrefab(
null,
null,
new Identifier(
"No identifier"));
1212 new SerializableEntityEditor(listBox.Content.RectTransform, newPrefab,
false,
false);
1214 box.Buttons[0].OnClicked += (b, d) =>
1220 box.Buttons[1].OnClicked += (b, d) =>
1222 if (
string.IsNullOrEmpty(nameBox.Text))
1224 nameBox.Flash(GUIStyle.Red);
1225 GUI.AddMessage(TextManager.Get(
"leveleditor.levelobjnameempty"), GUIStyle.Red);
1229 if (LevelObjectPrefab.Prefabs.Any(obj => obj.Identifier == nameBox.Text))
1231 nameBox.Flash(GUIStyle.Red);
1232 GUI.AddMessage(TextManager.Get(
"leveleditor.levelobjnametaken"), GUIStyle.Red);
1236 if (!File.Exists(texturePathBox.Text))
1238 texturePathBox.Flash(GUIStyle.Red);
1239 GUI.AddMessage(TextManager.Get(
"leveleditor.levelobjtexturenotfound"), GUIStyle.Red);
1243 System.Xml.XmlWriterSettings settings =
new System.Xml.XmlWriterSettings { Indent =
true };
1245 var newElement =
new XElement(nameBox.Text);
1246 newPrefab.Save(newElement);
1247 newElement.Add(
new XElement(
"Sprite",
1248 new XAttribute(
"texture", texturePathBox.Text),
1249 new XAttribute(
"sourcerect",
"0,0,100,100"),
1250 new XAttribute(
"origin",
"0.5,0.5")));
1253 #warning TODO: add a clear way to tack it into an existing content package?
1254 string modDir = Path.Combine(ContentPackage.LocalModsDir, nameBox.Text);
1255 Directory.CreateDirectory(modDir);
1257 string fileListPath = Path.Combine(modDir, ContentPackage.FileListFileName);
1258 string prefabFilePath = Path.Combine(modDir, $
"{nameBox.Text}.xml");
1260 var newMod =
new ModProject { Name = nameBox.Text };
1261 var newFile = ModProject.File.FromPath<LevelObjectPrefabsFile>(prefabFilePath);
1262 newMod.AddFile(newFile);
1264 XDocument fileListDoc = newMod.ToXDocument();
1265 Directory.CreateDirectory(Path.GetDirectoryName(fileListPath));
1268 XDocument prefabDoc =
new XDocument();
1269 var prefabFileRoot =
new XElement(
"LevelObjects");
1270 prefabFileRoot.Add(newElement);
1271 prefabDoc.Add(prefabFileRoot);
1274 ContentPackageManager.UpdateContentPackageList();
1276 var newRegularList = ContentPackageManager.EnabledPackages.Regular.ToList();
1277 newRegularList.Add(ContentPackageManager.RegularPackages.First(p => p.Name == nameBox.Text));
1278 ContentPackageManager.EnabledPackages.SetRegular(newRegularList);
1280 GameMain.LevelEditorScreen.UpdateLevelObjectsList();
static CoroutineStatus Running
static CoroutineStatus Success
static IReadOnlyCollection< Entity > GetEntities()
virtual void AddToGUIUpdateList(bool ignoreChildren=false, int order=0)
RectTransform RectTransform
IEnumerable< GUIComponent > Children
OnSelectedHandler OnSelected
static void AutoScaleAndNormalize(params GUITextBlock[] textBlocks)
Set the text scale of the GUITextBlocks so that they all use the same scale and can fit the text with...
static LevelEditorScreen LevelEditorScreen
static GameSession?? GameSession
static SpriteEditorScreen SpriteEditorScreen
static RasterizerState ScissorTestEnable
static int GraphicsHeight
static Lights.LightManager LightManager
static GameScreen GameScreen
static GameModePreset TestMode
void StartRound(string levelSeed, float? difficulty=null, LevelGenerationParams? levelGenerationParams=null)
static Location[] CreateDummyLocations(LevelData levelData, LocationType? forceLocationType=null)
static XmlWriter Create(string path, System.Xml.XmlWriterSettings settings)
static readonly List< Item > ItemList
List< ItemComponent > Components
static LevelData CreateRandom(string seed="", float? difficulty=null, LevelGenerationParams generationParams=null, bool requireOutpost=false)
OutpostGenerationParams ForceOutpostGenerationParams
override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
override void AddToGUIUpdateList()
By default, submits the screen's main GUIFrame and, if requested upon construction,...
override void DeselectEditorSpecific()
void TestLevelGenerationForErrors(int amountOfLevelsToGenerate)
override void Update(double deltaTime)
static readonly PrefabCollection< LevelGenerationParams > LevelParams
void DrawBack(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam)
readonly LevelData LevelData
List< ClusterLocation > AbyssResources
List< PathPoint > PathPoints
void DrawDebugOverlay(SpriteBatch spriteBatch, Camera cam)
float CrushDepth
The crush depth of a non-upgraded submarine in in-game coordinates. Note that this can be above the t...
void Update(float deltaTime, Camera cam)
static Level Generate(LevelData levelData, bool mirror, Location startLocation, Location endLocation, SubmarineInfo startOutpost=null, SubmarineInfo endOutpost=null)
void DrawFront(SpriteBatch spriteBatch, Camera cam)
List< InterestingPosition > PositionsOfInterest
List< int > LightSourceTriggerIndex
List< LightSourceParams > LightSourceParams
List< ChildObject > ChildObjects
void Update(float deltaTime)
void RenderLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, RenderTarget2D backgroundObstructor=null)
void AddLight(LightSource light)
LightSourceParams LightSourceParams
bool IsBackground
Background lights are drawn behind submarines and they don't cast shadows.
bool IsHidden
Is the entity hidden due to HiddenInGame being enabled or the layer the entity is in being hidden?
readonly Identifier Identifier
static readonly PrefabCollection< RuinGenerationParams > RuinParams
override void Update(double deltaTime)
override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
static void DrawFront(SpriteBatch spriteBatch, bool editing=false, Predicate< MapEntity > predicate=null)
static void DrawDamageable(SpriteBatch spriteBatch, Effect damageEffect, bool editing=false, Predicate< MapEntity > predicate=null)
static void Draw(SpriteBatch spriteBatch, bool editing=false)
Rectangle? Borders
Extents of the solid items/structures (ones with a physics body) and hulls
void SetPosition(Vector2 position, List< Submarine > checkd=null, bool forceUndockFromStaticSubmarines=true)
LocalizedString DisplayName
static IEnumerable< SubmarineInfo > SavedSubmarines