public virtual void ResolveResources(ResourceManager M59ResourceManager, bool RaiseChangedEvent) { if (OverlayFile != String.Empty) { if (RaiseChangedEvent) { Resource = M59ResourceManager.GetObject(OverlayFile); } else { resource = M59ResourceManager.GetObject(OverlayFile); } if (resource != null) { animation.GroupMax = resource.FrameSets.Count; } } foreach (SubOverlay obj in subOverlays) { obj.ResolveResources(M59ResourceManager, false); } // appearance update ProcessAppearance(true); }
/// <summary> /// Sets the ceiling texture to another num /// </summary> /// <param name="TextureNum"></param> /// <param name="TextureFile"></param> public void SetCeilingTexture(ushort TextureNum, BgfFile TextureFile) { string oldmaterial = MaterialNameCeiling; CeilingTexture = TextureNum; ResourceCeiling = TextureFile; if (ResourceCeiling != null && ResourceCeiling.Frames.Count > 0) { TextureCeiling = ResourceCeiling.Frames[0]; SpeedCeiling = GetSectorScrollSpeed(false, TextureCeiling.Width, TextureCeiling.Height); TextureNameCeiling = RooFile.GetNameForTexture( ResourceCeiling, 0); MaterialNameCeiling = RooFile.GetNameForMaterial( ResourceCeiling, 0, SpeedCeiling); } else { TextureCeiling = null; TextureNameCeiling = null; MaterialNameCeiling = null; SpeedCeiling = V2.ZERO; } if (TextureChanged != null) { TextureChanged(this, new SectorTextureChangedEventArgs(this, false, oldmaterial)); } }
/// <summary> /// Sets the floor texture to another num /// </summary> /// <param name="TextureNum"></param> /// <param name="TextureFile"></param> public void SetFloorTexture(ushort TextureNum, BgfFile TextureFile) { string oldmaterial = MaterialNameFloor; FloorTexture = TextureNum; ResourceFloor = TextureFile; if (ResourceFloor != null && ResourceFloor.Frames.Count > 0) { TextureFloor = ResourceFloor.Frames[0]; SpeedFloor = GetSectorScrollSpeed(true, TextureFloor.Width, TextureFloor.Height); TextureNameFloor = RooFile.GetNameForTexture( ResourceFloor, 0); MaterialNameFloor = RooFile.GetNameForMaterial( ResourceFloor, 0, SpeedFloor); } else { TextureFloor = null; TextureNameFloor = null; MaterialNameFloor = null; SpeedFloor = V2.ZERO; } if (TextureChanged != null) { TextureChanged(this, new SectorTextureChangedEventArgs(this, true, oldmaterial)); } }
/// <summary> /// Updates values of this instance to values taken from parameter instance. /// </summary> /// <param name="Model"></param> /// <param name="RaiseChangedEvent"></param> public override void UpdateFromModel(ObjectBase Model, bool RaiseChangedEvent) { base.UpdateFromModel(Model, RaiseChangedEvent); if (RaiseChangedEvent) { OverlayFileRID = Model.OverlayFileRID; NameRID = Model.NameRID; Flags.UpdateFromModel(Model.Flags, RaiseChangedEvent); LightingInfo.UpdateFromModel(Model.LightingInfo, RaiseChangedEvent); FirstAnimationType = Model.FirstAnimationType; ColorTranslation = Model.ColorTranslation; Effect = Model.Effect; if (Animation != null) { Animation.PropertyChanged -= OnAnimationPropertyChanged; } Animation = Model.Animation; Animation.PropertyChanged += OnAnimationPropertyChanged; subOverlays.Clear(); subOverlays.AddRange(Model.SubOverlays); Name = Model.Name; OverlayFile = Model.OverlayFile; Resource = Model.Resource; } else { overlayFileRID = Model.OverlayFileRID; nameRID = Model.NameRID; Flags.UpdateFromModel(Model.Flags, RaiseChangedEvent); LightingInfo.UpdateFromModel(Model.LightingInfo, RaiseChangedEvent); firstAnimationType = Model.FirstAnimationType; colorTranslation = Model.ColorTranslation; effect = Model.Effect; if (animation != null) { animation.PropertyChanged -= OnAnimationPropertyChanged; } animation = Model.Animation; animation.PropertyChanged += OnAnimationPropertyChanged; subOverlays.Clear(); subOverlays.AddRange(Model.SubOverlays); name = Model.Name; overlayFile = Model.OverlayFile; resource = Model.Resource; } // appearance update ProcessAppearance(true); }
/// <summary> /// Loads all BGF from subfolder "bgf" in document root /// </summary> public static void Load() { cache.Clear(); string filePath = HttpRuntime.AppDomainAppPath + "bgf/"; string[] files = Directory.GetFiles(filePath, "*.bgf"); uint num = 1; foreach (string s in files) { try { // get file info FileInfo info = new FileInfo(s); // read from disk and decompress all (important!) BgfFile bgf = new BgfFile(s); bgf.DecompressAll(); Entry entry = new Entry(); entry.Bgf = bgf; // get filesystem lastwrite date DateTime fileDate = info.LastWriteTimeUtc; // store truncated to seconds entry.LastModified = fileDate.AddTicks(-(fileDate.Ticks % TimeSpan.TicksPerSecond)); entry.Size = info.Length; // set pseudo id (for appearance hashing) entry.Num = num; num++; // add to cache cache.TryAdd(bgf.Filename, entry); } catch (Exception) { } } // save when the cache was filled DateTime now = DateTime.UtcNow; LastModified = now.AddTicks(-(now.Ticks % TimeSpan.TicksPerSecond)); LastModifiedStamp = (now.Ticks - 621355968000000000) / 10000000; // save array variant for iteration //pairs = BgfCache.cache.ToArray(); // compact large object heap next run GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; // execute maximum GC run GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); }
public override void Clear(bool RaiseChangedEvent) { base.Clear(RaiseChangedEvent); if (RaiseChangedEvent) { OverlayFileRID = 0; NameRID = 0; LightFlags = 0; LightIntensity = 0; LightColor = 0; FirstAnimationType = 0; ColorTranslation = 0; Effect = 0; if (animation != null) { animation.PropertyChanged -= OnAnimationPropertyChanged; } Animation = new AnimationNone(); animation.PropertyChanged += OnAnimationPropertyChanged; Name = String.Empty; OverlayFile = String.Empty; Resource = null; } else { overlayFileRID = 0; nameRID = 0; lightFlags = 0; lightIntensity = 0; lightColor = 0; firstAnimationType = 0; colorTranslation = 0; effect = 0; if (animation != null) { animation.PropertyChanged -= OnAnimationPropertyChanged; } animation = new AnimationNone(); animation.PropertyChanged += OnAnimationPropertyChanged; name = String.Empty; overlayFile = String.Empty; resource = null; } flags.Clear(RaiseChangedEvent); subOverlays.Clear(); }
public void ResolveResources(ResourceManager M59ResourceManager, bool RaiseChangedEvent) { if (RaiseChangedEvent) { Resource = M59ResourceManager.GetRoomTexture(textureNum); } else { resource = M59ResourceManager.GetRoomTexture(textureNum); } }
public override void Clear(bool RaiseChangedEvent) { base.Clear(RaiseChangedEvent); if (RaiseChangedEvent) { Resource = null; } else { resource = null; } }
public virtual void UpdateFromModel(ResourceIDBGF Model, bool RaiseChangedEvent) { base.UpdateFromModel(Model, RaiseChangedEvent); if (RaiseChangedEvent) { Resource = Model.Resource; } else { resource = Model.Resource; } }
/// <summary> /// Sets middle texture to another num /// </summary> /// <param name="TextureNum"></param> /// <param name="TextureFile"></param> /// <param name="ResetAnimation"></param> public void SetMiddleTexture(ushort TextureNum, BgfFile TextureFile, bool ResetAnimation = true) { ushort group = (animation != null) ? animation.CurrentGroup : (ushort)1; int frameidx = 0; string oldmaterial = MaterialNameMiddle; MiddleTexture = TextureNum; ResourceMiddle = TextureFile; if (ResourceMiddle != null && ResourceMiddle.Frames.Count > 0) { // possibly reset animation if (animation != null && ResetAnimation) { animation.SetValues(1, ResourceMiddle.FrameSets.Count, false); group = animation.CurrentGroup; } frameidx = ResourceMiddle.GetFrameIndex(group, 0); frameidx = Math.Max(frameidx, 0); if (ResourceMiddle.Frames.Count > frameidx) { TextureMiddle = ResourceMiddle.Frames[frameidx]; SpeedMiddle = GetWallScrollSpeed(TextureMiddle.Width, TextureMiddle.Height); } else { TextureMiddle = null; SpeedMiddle = V2.ZERO; } TextureNameMiddle = RooFile.GetNameForTexture( ResourceMiddle, frameidx); MaterialNameMiddle = RooFile.GetNameForMaterial( ResourceMiddle, frameidx, SpeedMiddle); } else { TextureMiddle = null; SpeedMiddle = V2.ZERO; TextureNameMiddle = null; MaterialNameMiddle = null; } if (TextureChanged != null) { TextureChanged(this, new WallTextureChangedEventArgs(this, WallPartType.Middle, oldmaterial)); } }
public void ResolveResources(ResourceManager M59ResourceManager, bool RaiseChangedEvent) { if (Name != String.Empty) { if (RaiseChangedEvent) { Resource = M59ResourceManager.GetObject(OverlayFile); } else { resource = M59ResourceManager.GetObject(OverlayFile); } } }
public virtual void ResolveResources(ResourceManager M59ResourceManager, bool RaiseChangedEvent) { if (name != String.Empty) { if (RaiseChangedEvent) { Resource = M59ResourceManager.GetObject(name); } else { resource = M59ResourceManager.GetObject(name); } } }
/// <summary> /// Preloads all elements in the RoomTextures dictionary. /// </summary> public void PreloadRoomTextures() { IEnumerator <KeyValuePair <string, BgfFile> > it = RoomTextures.GetEnumerator(); BgfFile file; while (it.MoveNext()) { // load file = new BgfFile(Path.Combine(Config.RoomTexturesFolder, it.Current.Key)); file.DecompressAll(); // update RoomTextures.TryUpdate(it.Current.Key, file, null); } GC.Collect(2); }
/// <summary> /// Stars loading all roomtextures in a background thread. /// </summary> protected void LoadThreadRoomTextures() { IEnumerator <KeyValuePair <string, BgfFile> > it = RoomTextures.GetEnumerator(); BgfFile file; while (it.MoveNext()) { // load file = new BgfFile(Path.Combine(RoomTexturesFolder, it.Current.Key)); file.DecompressAll(); // update RoomTextures.TryUpdate(it.Current.Key, file, null); queueAsyncFilesLoaded.Enqueue(it.Current.Key); } }
/// <summary> /// Sets lower texture to another num /// </summary> /// <param name="TextureNum"></param> /// <param name="TextureFile"></param> public void SetUpperTexture(ushort TextureNum, BgfFile TextureFile) { ushort group = (animation != null) ? animation.CurrentGroup : (ushort)1; int frameidx = 0; string oldmaterial = MaterialNameUpper; UpperTexture = TextureNum; ResourceUpper = TextureFile; if (ResourceUpper != null && ResourceUpper.Frames.Count > 0) { frameidx = ResourceUpper.GetFrameIndex(group, 0); frameidx = Math.Max(frameidx, 0); if (ResourceUpper.Frames.Count > frameidx) { TextureUpper = ResourceUpper.Frames[frameidx]; SpeedUpper = GetWallScrollSpeed(TextureUpper.Width, TextureUpper.Height); } else { TextureUpper = null; SpeedUpper = V2.ZERO; } TextureNameUpper = RooFile.GetNameForTexture( ResourceUpper, frameidx); MaterialNameUpper = RooFile.GetNameForMaterial( ResourceUpper, frameidx, SpeedUpper); } else { TextureUpper = null; SpeedUpper = V2.ZERO; TextureNameUpper = null; MaterialNameUpper = null; } if (TextureChanged != null) { TextureChanged(this, new WallTextureChangedEventArgs(this, WallPartType.Upper, oldmaterial)); } }
/// <summary> /// Tries to retrieve a BGF file from the RoomTextures dictionary. /// Will load the file from disk, if not yet loaded. /// </summary> /// <param name="File"></param> /// <returns></returns> public BgfFile GetRoomTexture(string File) { BgfFile bgfFile = null; // if the file is known if (RoomTextures.TryGetValue(File, out bgfFile)) { // haven't loaded it yet? if (bgfFile == null) { byte[] buffer; // get file byte buffer if (!fileBuffers.TryPop(out buffer)) { buffer = new byte[FILEBUFFERSIZE]; } string file = RoomTexturesFolder + "/" + File; // load to mem if (Util.LoadFileToBuffer(file, buffer)) { // load it bgfFile = new BgfFile(file, buffer); // update the registry if (RoomTextures.TryUpdate(File, bgfFile, null)) { numLoadedRoomTextures++; } } else { Logger.Log(MODULENAME, LogType.Error, "Failed to load file (possibly too big?): " + File); } fileBuffers.Push(buffer); } } return(bgfFile); }
public void ResolveResources(ResourceManager M59ResourceManager, bool RaiseChangedEvent) { if (Name != String.Empty) { if (RaiseChangedEvent) { Resource = M59ResourceManager.GetObject(Name); } else { resource = M59ResourceManager.GetObject(Name); } if (resource != null) { animation.GroupMax = resource.FrameSets.Count; } } }
/// <summary> /// Tries to retrieve a BGF file from the RoomTextures dictionary. /// Will load the file from disk, if not yet loaded. /// </summary> /// <param name="File"></param> /// <returns></returns> public BgfFile GetRoomTexture(string File) { BgfFile bgfFile = null; // if the file is known if (RoomTextures.TryGetValue(File, out bgfFile)) { // haven't loaded it yet? if (bgfFile == null) { // load it bgfFile = new BgfFile(RoomTexturesFolder + "/" + File); // update the registry RoomTextures.TryUpdate(File, bgfFile, null); } } return(bgfFile); }
/// <summary> /// Tries to retrieve a BGF file from the Objects dictionary. /// Will load the file from disk, if not yet loaded. /// </summary> /// <param name="File">Plain filename with extension (e.g. mushroom.bgf)</param> /// <returns></returns> public BgfFile GetObject(string File) { BgfFile bgfFile = null; // if the file is known if (Objects.TryGetValue(File, out bgfFile)) { // haven't loaded it yet? if (bgfFile == null) { // load it bgfFile = new BgfFile(Config.ObjectsFolder + "/" + File); // update the registry Objects.TryUpdate(File, bgfFile, null); } } return(bgfFile); }
public void ResolveResources(ResourceManager M59ResourceManager, bool RaiseChangedEvent) { if (OverlayFile != String.Empty) { if (RaiseChangedEvent) { Resource = M59ResourceManager.GetObject(OverlayFile); if (resource != null) { animation.GroupMax = resource.FrameSets.Count; motionAnimation.GroupMax = resource.FrameSets.Count; } } else { resource = M59ResourceManager.GetObject(OverlayFile); if (resource != null) { animation.GroupMax = resource.FrameSets.Count; motionAnimation.GroupMax = resource.FrameSets.Count; } } } foreach (SubOverlay obj in subOverlays) { obj.ResolveResources(M59ResourceManager, false); } foreach (SubOverlay obj in motionSubOverlays) { obj.ResolveResources(M59ResourceManager, false); } }
private void btnOK_Click(object sender, EventArgs e) { if (Directory.Exists(txtSource.Text) && Directory.Exists(txtTarget.Text)) { string[] files = Directory.GetFiles(txtSource.Text, "*.bgf"); switch (Mode) { case SourceTargetMode.Extract: foreach (string file in files) { try { BgfFile bgf = new BgfFile(file); bgf.WriteXmlAndBMPs(txtTarget.Text + "\\" + bgf.Filename); txtLog.Text += "Extracted " + bgf.Filename + ".bgf" + Environment.NewLine; } catch (Exception) { txtLog.Text += "Error with file " + file; } } break; case SourceTargetMode.Decompress: foreach (string file in files) { try { BgfFile bgf = new BgfFile(file); foreach (BgfBitmap bitmap in bgf.Frames) { bitmap.IsCompressed = false; } bgf.Save(txtTarget.Text + "\\" + bgf.Filename + ".bgf"); txtLog.Text += "Decompressed " + bgf.Filename + ".bgf" + Environment.NewLine; } catch (Exception) { txtLog.Text += "Error with file " + file; } } break; case SourceTargetMode.SetVersion9: foreach (string file in files) { try { BgfFile bgf = new BgfFile(file); bgf.Version = BgfFile.VERSION9; bgf.Save(txtTarget.Text + "\\" + bgf.Filename + ".bgf"); txtLog.Text += "Converted " + bgf.Filename + ".bgf" + " to V9 (crush32)" + Environment.NewLine; } catch (Exception) { txtLog.Text += "Error with file " + file; } } break; case SourceTargetMode.SetVersion10: foreach (string file in files) { try { BgfFile bgf = new BgfFile(file); bgf.Version = BgfFile.VERSION10; bgf.Save(txtTarget.Text + "\\" + bgf.Filename + ".bgf"); txtLog.Text += "Converted " + bgf.Filename + ".bgf" + " to V10 (zlib)" + Environment.NewLine; } catch (Exception) { txtLog.Text += "Error with file " + file; } } break; case SourceTargetMode.SetVersion10FromVale: foreach (string file in files) { try { BgfFile bgf = new BgfFile(file); bgf.ConvertFromVale(); bgf.Version = BgfFile.VERSION10; bgf.Save(txtTarget.Text + "\\" + bgf.Filename + ".bgf"); txtLog.Text += "Converted " + bgf.Filename + ".bgf" + " to V10 (zlib)" + Environment.NewLine; } catch (Exception) { txtLog.Text += "Error with file " + file; } } break; } } }
public void Collect(string PathBgf, string PathPng) { items.Clear(); string[] bgfs = Directory.GetFiles(PathBgf, "*.bgf"); foreach (string sbgf in bgfs) { BgfFile bgfFile = new BgfFile(sbgf); for (int i = 0; i < bgfFile.Frames.Count; i++) { BgfBitmap frame = bgfFile.Frames[i]; // create new item Item item = new Item(); // build file-frame name item.Frame = bgfFile.Filename + "-" + i.ToString(); item.Shrink = bgfFile.ShrinkFactor; // set values from bgf frame item.Bgf = frame; item.BgfWidth = frame.Width; item.BgfHeight = frame.Height; item.BgfRatio = (float)frame.Width / (float)frame.Height; // build png path string pngname = PathPng + "/" + bgfFile.Filename + "-" + i.ToString() + FileExtensions.PNG; if (File.Exists(pngname)) { item.Png = new Bitmap(pngname); item.PngWidth = item.Png.Width; item.PngHeight = item.Png.Height; item.PngRatio = (float)item.Png.Width / (float)item.Png.Height; // scale between bgf and png item.Scale = (float)item.Png.Width / (float)frame.Width; // compare ratio if (item.PngRatio != item.BgfRatio) { item.State = "ERROR"; } else { item.State = "OK"; } } else { item.State = "MISS"; } // add new item items.Add(item); } } gridTextures.DataSource = items; }
static void Main() { // .net stuff Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // initialize color palettes PalettesGDI.Initialize(); // init bgf data model CurrentFile = new BgfFile(); CurrentFile.Frames.AllowEdit = true; // init roomobject model for viewer RoomObject = new RoomObject(); RoomObject.Resource = CurrentFile; // init imagecomposer for this roomobject ImageComposer = new ImageComposerGDI <RoomObject>(); ImageComposer.UseViewerFrame = true; ImageComposer.DataSource = RoomObject; // init mainform MainForm = new MainForm(); MainForm.FormClosed += OnMainFormFormClosed; MainForm.Show(); // init shrinkform SettingsForm = new SettingsForm(); SettingsForm.DataBindings.Add("Version", CurrentFile, "Version"); SettingsForm.DataBindings.Add("ShrinkFactor", CurrentFile, "ShrinkFactor"); SettingsForm.DataBindings.Add("Name", CurrentFile, "Name"); // init addframsetindexform AddFrameSetIndexForm = new AddFrameSetIndexForm(); // init ticker stopWatch = new Stopwatch(); stopWatch.Start(); // set running IsRunning = true; // start mainthread loop while (IsRunning) { long oldTick = Tick; // update current tick Tick = stopWatch.ElapsedTicks / MSTICKDIVISOR; long span = Tick - oldTick; // update roomobject if (IsPlaying) { RoomObject.Tick(Tick, span); } // process window messages / events Application.DoEvents(); // sleep Thread.Sleep(1); } }
static void Main() { // .net stuff Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // init bgf data model CurrentFile = new BgfFile(); CurrentFile.Frames.AllowEdit = true; // init roomobject model for viewer RoomObject = new RoomObject(); RoomObject.Resource = CurrentFile; // init mainform MainForm = new MainForm(); MainForm.FormClosed += OnMainFormFormClosed; MainForm.Show(); ImageComposerGDI <RoomObject> .Cache.IsEnabled = false; // init shrinkform SettingsForm = new SettingsForm(); SettingsForm.DataBindings.Add("Version", CurrentFile, "Version"); SettingsForm.DataBindings.Add("ShrinkFactor", CurrentFile, "ShrinkFactor"); SettingsForm.DataBindings.Add("Name", CurrentFile, "Name"); // init addframsetindexform AddFrameSetIndexForm = new AddFrameSetIndexForm(); // init ticker stopWatch = new Stopwatch(); stopWatch.Start(); // set running IsRunning = true; string[] args = Environment.GetCommandLineArgs(); // load file passed by arguments if (args.Length > 1) { Load(args[1]); } // start mainthread loop while (IsRunning) { long oldTick = Tick; // update current tick Tick = stopWatch.ElapsedTicks / MSTICKDIVISOR; long span = Tick - oldTick; // update roomobject //if (IsPlaying) RoomObject.Tick(Tick, span); // process window messages / events Application.DoEvents(); // sleep Thread.Sleep(1); } }
protected void Calculate( ObjectBase Data, BgfBitmap MainFrame, bool UseViewerFrame = true, bool ApplyYOffset = true, byte RootHotspotIndex = 0, Real Quality = DEFAULTQUALITY, bool ScalePow2 = false, uint Width = 0, uint Height = 0, bool CenterVertical = false, bool CenterHorizontal = false, bool IsCustomShrink = false, Real CustomShrink = 1.0f) { BgfBitmap mainFrame = MainFrame; BgfFile mainResource = Data.Resource; byte mainColor = Data.ColorTranslation; BgfBitmap subOvFrame; BgfBitmapHotspot subOvHotspot; SubOverlay subOvParent; BgfBitmap subOvParentFrame; BgfBitmapHotspot subOvParentHotspot; bool rootSpotFound = false; // use custom compose root (suboverlay=mainoverlay) // if it's not found, fallback to full compose if (RootHotspotIndex > 0) { SubOverlay subOv = Data.GetSubOverlayByHotspot(RootHotspotIndex); if (subOv != null) { rootSpotFound = true; if (UseViewerFrame) { mainFrame = subOv.ViewerFrame; } else { mainFrame = subOv.FrontFrame; } mainResource = subOv.Resource; mainColor = subOv.ColorTranslation; } } if (mainFrame != null && mainResource != null) { Bgf = mainFrame; BgfColor = mainColor; size.X = (Real)mainFrame.Width / (Real)mainResource.ShrinkFactor; size.Y = (Real)mainFrame.Height / (Real)mainResource.ShrinkFactor; origin.X = (Real)mainFrame.XOffset / (Real)mainResource.ShrinkFactor; origin.Y = (Real)mainFrame.YOffset / (Real)mainResource.ShrinkFactor; MaxShrink = mainResource.ShrinkFactor; // used to calculate the boundingbox V2 min = new V2(Origin.X, Origin.Y); V2 max = new V2(Size.X, Size.Y); if (ApplyYOffset) { if (origin.X > 0.0f) { max.X += origin.X; } if (origin.Y > 0.0f) { max.Y += origin.Y; } } else { max += origin; } Real x, y; // walk suboverlay structure foreach (SubOverlay subOv in Data.CurrentSubOverlays) { if (UseViewerFrame) { subOvFrame = subOv.ViewerFrame; subOvHotspot = subOv.ViewerHotspot; subOvParent = subOv.ViewerParent; } else { subOvFrame = subOv.FrontFrame; subOvHotspot = subOv.FrontHotspot; subOvParent = subOv.FrontParent; } bool isSubRoot = (subOvParent != null && subOvParent.HotSpot == RootHotspotIndex); if (subOv.Resource != null && subOvFrame != null && subOvHotspot != null && (RootHotspotIndex <= 0 || !rootSpotFound || isSubRoot)) { SubOverlay.RenderInfo subOvInfo = new SubOverlay.RenderInfo(); // save subov & bitmap subOvInfo.SubOverlay = subOv; subOvInfo.Bgf = subOvFrame; // calculate the size of this suboverlay subOvInfo.Size.X = (Real)subOvFrame.Width / (Real)subOv.Resource.ShrinkFactor; subOvInfo.Size.Y = (Real)subOvFrame.Height / (Real)subOv.Resource.ShrinkFactor; // update maxshrink if greater if (subOv.Resource.ShrinkFactor > MaxShrink) { MaxShrink = subOv.Resource.ShrinkFactor; } // CASE 1: SubOverlay on mainoverlay if (subOvParent == null || isSubRoot) { // calculate the origin of this suboverlay on the mainoverlay subOvInfo.Origin.X = mainFrame.XOffset + ((Real)subOvHotspot.X) + ((Real)subOvFrame.XOffset); subOvInfo.Origin.Y = mainFrame.YOffset + ((Real)subOvHotspot.Y) + ((Real)subOvFrame.YOffset); subOvInfo.Origin.X /= mainResource.ShrinkFactor; subOvInfo.Origin.Y /= mainResource.ShrinkFactor; // determine type of hotspot if (subOvHotspot.Index < 0) { subOvInfo.HotspotType = HotSpotType.HOTSPOT_UNDER; } else { subOvInfo.HotspotType = HotSpotType.HOTSPOT_OVER; } } // CASE 2: SubOverlay on SubOverlay on MainOverlay else { if (UseViewerFrame) { subOvParentFrame = subOvParent.ViewerFrame; subOvParentHotspot = subOvParent.ViewerHotspot; } else { subOvParentFrame = subOvParent.FrontFrame; subOvParentHotspot = subOvParent.FrontHotspot; } if (subOvParentHotspot != null && subOvParentFrame != null && subOvParent.Resource != null) { // calculate the origin of this suboverlay on the suboverlay on the mainoverlay subOvInfo.Origin.X = (mainFrame.XOffset + (Real)subOvParentHotspot.X + (Real)subOvParentFrame.XOffset) / (Real)mainResource.ShrinkFactor; subOvInfo.Origin.X += ((Real)subOvHotspot.X + (Real)subOvFrame.XOffset) / (Real)subOvParent.Resource.ShrinkFactor; subOvInfo.Origin.Y = (mainFrame.YOffset + (Real)subOvParentHotspot.Y + (Real)subOvParentFrame.YOffset) / (Real)mainResource.ShrinkFactor; subOvInfo.Origin.Y += ((Real)subOvHotspot.Y + (Real)subOvFrame.YOffset) / (Real)subOvParent.Resource.ShrinkFactor; // determine type of nested hotspot if (subOvParentHotspot.Index > 0 && subOvHotspot.Index > 0) { subOvInfo.HotspotType = HotSpotType.HOTSPOT_OVEROVER; } else if (subOvParentHotspot.Index > 0 && subOvHotspot.Index < 0) { subOvInfo.HotspotType = HotSpotType.HOTSPOT_OVERUNDER; } else if (subOvParentHotspot.Index < 0 && subOvHotspot.Index > 0) { subOvInfo.HotspotType = HotSpotType.HOTSPOT_UNDEROVER; } else if (subOvParentHotspot.Index < 0 && subOvHotspot.Index < 0) { subOvInfo.HotspotType = HotSpotType.HOTSPOT_UNDERUNDER; } } } // update max boundingbox if (subOvInfo.Origin.X < min.X) { min.X = subOvInfo.Origin.X; } if (subOvInfo.Origin.Y < min.Y) { min.Y = subOvInfo.Origin.Y; } x = subOvInfo.Origin.X + subOvInfo.Size.X; y = subOvInfo.Origin.Y + subOvInfo.Size.Y; if (x > max.X) { max.X = x; } if (y > max.Y) { max.Y = y; } // save info for this suboverlay SubBgf.Add(subOvInfo); } } // get dimension from boundingbox dimension.X = Math.Abs(max.X - min.X); dimension.Y = Math.Abs(max.Y - min.Y); // move all origins so minimum hits 0/0 // preparation for drawing (pixel origin is 0/0) Translate(-min); // get the center of the dimension box // this is also the center of our image after the translate above V2 bbCenter = dimension * 0.5f; // get the center of the main overlay V2 mainOriginCenter = Origin + (Size * 0.5f); // move the x center of the main overlay to the x center of dimensionbox V2 centerMove = new V2(bbCenter.X - mainOriginCenter.X, 0.0f); Translate(centerMove); // since this moves a part outside the dimension box // we need to add this size of the move to the dimension, // to the right AND left side, so our centering above stays centered // then we remove to the center. V2 center = new V2(Math.Abs(centerMove.X), 0.0f); dimension.X += center.X * 2.0f; Translate(center); // scale so highest resolution resource has 1:1 ratio (no downscale) // or to user provided shrink value Scale(IsCustomShrink ? CustomShrink : (Real)MaxShrink); // user defined sizes if (Width > 0 && Height > 0) { // use user given size V2 userSize = new V2(Width, Height); // scale so we use at least all pixels either from upscaled width or height ScaleToBox(userSize, CenterHorizontal, CenterVertical, !IsCustomShrink); } else { Real maxQuality = Quality * QUALITYBASE; Real ratioX = maxQuality / dimension.X; Real ratioY = maxQuality / dimension.Y; if (ratioX <= ratioY && ratioX < 1.0f) { Scale(ratioX); } else if (ratioX > ratioY && ratioY < 1.0f) { Scale(ratioY); } // scale up to pow2 if set if (ScalePow2) { // get next power of 2 size V2 pow2Size = new V2( MathUtil.NextPowerOf2((uint)System.Math.Ceiling(dimension.X)), MathUtil.NextPowerOf2((uint)System.Math.Ceiling(dimension.Y))); // scale so we use at least all pixels either from upscaled width or height ScaleToBox(pow2Size, CenterHorizontal, CenterVertical, !IsCustomShrink); } } // calculate the world-size (shrink=1) of the composed object from dimension, uv-coordinates and scaling worldsize.X = (uvend.X * dimension.X) / Scaling; worldsize.Y = (uvend.Y * dimension.Y) / Scaling; } }