protected override unsafe void DrawSubOverlay(SubOverlay.RenderInfo RenderInfo) { // todo: negative positions not supported by method below if (RenderInfo.Origin.X < 0.0f || RenderInfo.Origin.Y < 0.0f) { return; } RenderInfo.Bgf.FillPixelDataAsA8R8G8B8TransparencyBlackScaled( (uint *)pixelData.Scan0.ToPointer(), (uint)Image.Width, (uint)Image.Height, Convert.ToUInt32(RenderInfo.Origin.X), Convert.ToUInt32(RenderInfo.Origin.Y), Convert.ToUInt32(RenderInfo.Size.X), Convert.ToUInt32(RenderInfo.Size.Y), RenderInfo.SubOverlay.ColorTranslation); }
protected override void DrawSubOverlay(SubOverlay.RenderInfo RenderInfo) { // copy from this rectangle in source Rectangle fromRectangle = new Rectangle(0, 0, (int)RenderInfo.Bgf.Width, (int)RenderInfo.Bgf.Height); // copy to this rectangle in destination Rectangle toRectangle = new Rectangle( Convert.ToInt32(RenderInfo.Origin.X), Convert.ToInt32(RenderInfo.Origin.Y), Convert.ToInt32(RenderInfo.Size.X), Convert.ToInt32(RenderInfo.Size.Y)); // get subimage to draw Bitmap bmp = RenderInfo.Bgf.GetBitmap(RenderInfo.SubOverlay.ColorTranslation); // draw drawTo.DrawImage(bmp, toRectangle, fromRectangle, GraphicsUnit.Pixel); // dispose subimage bmp.Dispose(); }
/// <summary> /// Override with code drawing suboverlays /// </summary> /// <param name="RenderInfo"></param> protected abstract void DrawSubOverlay(SubOverlay.RenderInfo RenderInfo);
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; } }