diff --git a/Engine/source/T3D/fps/guiCrossHairHud.cpp b/Engine/source/T3D/fps/guiCrossHairHud.cpp index eaa318c53..6e6dc2fce 100644 --- a/Engine/source/T3D/fps/guiCrossHairHud.cpp +++ b/Engine/source/T3D/fps/guiCrossHairHud.cpp @@ -30,7 +30,11 @@ #include "T3D/shapeBase.h" #include "gfx/gfxDrawUtil.h" #include "console/engineAPI.h" - +#include "gui/core/guiOffscreenCanvas.h" +#include "T3D/tsStatic.h" +#include "materials/baseMatInstance.h" +#include "materials/matInstance.h" +#include "materials/materialDefinition.h" //----------------------------------------------------------------------------- /// Vary basic cross hair hud. @@ -46,12 +50,14 @@ class GuiCrossHairHud : public GuiBitmapCtrl LinearColorF mDamageFrameColor; Point2I mDamageRectSize; Point2I mDamageOffset; + PlatformTimer* mFrameTime; protected: void drawDamage(Point2I offset, F32 damage, F32 opacity); public: GuiCrossHairHud(); + ~GuiCrossHairHud(); void onRender( Point2I, const RectI &) override; static void initPersistFields(); @@ -95,6 +101,12 @@ GuiCrossHairHud::GuiCrossHairHud() mDamageFrameColor.set( 1.0f, 0.6f, 0.0f, 1.0f ); mDamageRectSize.set(50, 4); mDamageOffset.set(0,32); + mFrameTime = PlatformTimer::create(); +} + +GuiCrossHairHud::~GuiCrossHairHud() +{ + SAFE_DELETE(mFrameTime); } void GuiCrossHairHud::initPersistFields() @@ -114,13 +126,14 @@ void GuiCrossHairHud::initPersistFields() void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) { + GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; // Must have a connection and player control object GameConnection* conn = GameConnection::getConnectionToServer(); if (!conn) return; - GameBase* control = dynamic_cast(conn->getCameraObject()); + /*GameBase* control = dynamic_cast(conn->getCameraObject()); if (!control || !(control->getTypeMask() & ObjectMask) || !conn->isFirstPerson()) - return; + return;*/ // Parent render. Parent::onRender(offset,updateRect); @@ -139,11 +152,61 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) // Collision info. We're going to be running LOS tests and we // don't want to collide with the control object. - static U32 losMask = TerrainObjectType | ShapeBaseObjectType; - control->disableCollision(); + static U32 losMask = TerrainObjectType | ShapeBaseObjectType | StaticShapeObjectType; + //control->disableCollision(); RayInfo info; if (gClientContainer.castRay(camPos, endPos, losMask, &info)) { + // is this a tsstatic? then it could be a offscreen canvas, check the list. + if (TSStatic* ts = dynamic_cast(info.object)) + { + if (mFrameTime->getElapsedMs() > 32) + { + mFrameTime->reset(); + + Point3F newStart, newEnd; + ts->getWorldTransform().mulP(camPos, &newStart); + ts->getWorldTransform().mulP(endPos, &newEnd); + + newStart.convolveInverse(ts->getScale()); + newEnd.convolveInverse(ts->getScale()); + + info.generateTexCoord = true; + if (ts->getShapeInstance()->castRayOpcode(0, newStart, newEnd, &info)) + { + MatInstance* matInst = dynamic_cast(info.material); + if (matInst) + { + Material* mat = matInst->getMaterial(); + if (mat && mat->getDiffuseMapAsset(0).notNull() && mat->getDiffuseMapAsset(0)->isNamedTarget()) + { + String canvasName = String(mat->getDiffuseMapAsset(0)->getImageFile()).substr(1, (U32)strlen(mat->getDiffuseMapAsset(0)->getImageFile()) - 1); + for (GuiOffscreenCanvas* canvas : GuiOffscreenCanvas::sList) + { + if (canvas->getTarget()->getName() == canvasName) + { + if (!canvas->canInteract() || canvas->getMaxInteractDistance() < info.distance) + { + break; + } + + Point2I canvasSize = canvas->getWindowSize(); + Point2I newCursorPos(mRound(mClampF((info.texCoord.x * canvasSize.x), 0.0f, (F32)canvasSize.x)), + mRound(mClampF((info.texCoord.y * canvasSize.y), 0.0f, (F32)canvasSize.y))); + + canvas->setCursorPos(newCursorPos); + canvas->markDirty(); + GuiOffscreenCanvas::sActiveOffscreenCanvas = canvas; + break; + } + } + } + } + } + } + + } + // Hit something... but we'll only display health for named // ShapeBase objects. Could mask against the object type here // and do a static cast if it's a ShapeBaseObjectType, but this @@ -157,7 +220,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect) } // Restore control object collision - control->enableCollision(); + //control->enableCollision(); } diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index d00c3024a..b14f7ece2 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -690,6 +690,12 @@ bool GuiCanvas::processInputEvent(InputEventInfo &inputEvent) mConsumeLastInputEvent = true; mLastInputDeviceType = inputEvent.deviceType; + // If we have an active offscreen canvas, give it the input + if (GuiOffscreenCanvas::sActiveOffscreenCanvas && + (GuiOffscreenCanvas::sActiveOffscreenCanvas != this) && + GuiOffscreenCanvas::sActiveOffscreenCanvas->processInputEvent(inputEvent)) + return mConsumeLastInputEvent; + // First call the general input handler (on the extremely off-chance that it will be handled): if (mFirstResponder && mFirstResponder->onInputEvent(inputEvent)) { diff --git a/Engine/source/gui/core/guiOffscreenCanvas.cpp b/Engine/source/gui/core/guiOffscreenCanvas.cpp index 522882b14..55562b028 100644 --- a/Engine/source/gui/core/guiOffscreenCanvas.cpp +++ b/Engine/source/gui/core/guiOffscreenCanvas.cpp @@ -9,6 +9,7 @@ IMPLEMENT_CONOBJECT(GuiOffscreenCanvas); +GuiOffscreenCanvas* GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL; Vector GuiOffscreenCanvas::sList; GuiOffscreenCanvas::GuiOffscreenCanvas() @@ -33,7 +34,8 @@ void GuiOffscreenCanvas::initPersistFields() addField( "targetName", TypeRealString, Offset( mTargetName, GuiOffscreenCanvas ), ""); addField( "dynamicTarget", TypeBool, Offset( mDynamicTarget, GuiOffscreenCanvas ), ""); addField( "useDepth", TypeBool, Offset( mUseDepth, GuiOffscreenCanvas ), ""); - + addField("canInteract", TypeBool, Offset(mCanInteract, GuiOffscreenCanvas), ""); + addField("maxInteractDistance", TypeF32, Offset(mMaxInteractDistance, GuiOffscreenCanvas), ""); Parent::initPersistFields(); } diff --git a/Engine/source/gui/core/guiOffscreenCanvas.h b/Engine/source/gui/core/guiOffscreenCanvas.h index 0d7a79d35..de8c221b8 100644 --- a/Engine/source/gui/core/guiOffscreenCanvas.h +++ b/Engine/source/gui/core/guiOffscreenCanvas.h @@ -38,6 +38,8 @@ public: void _teardownTargets(); NamedTexTargetRef getTarget() { return &mNamedTarget; } + bool canInteract() { return mCanInteract; } + F32 getMaxInteractDistance() { return mMaxInteractDistance; } void markDirty() { mTargetDirty = true; } @@ -59,9 +61,12 @@ protected: bool mUseDepth; GFXTexHandle mTargetDepth; + bool mCanInteract; + F32 mMaxInteractDistance; public: static Vector sList; + static GuiOffscreenCanvas* sActiveOffscreenCanvas; }; #endif diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml new file mode 100644 index 000000000..fc9196375 --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/ScreenTarget.asset.taml @@ -0,0 +1,11 @@ + + + + + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml new file mode 100644 index 000000000..75d507122 --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_base_mat.asset.taml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml new file mode 100644 index 000000000..db7490eea --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_screen_mat.asset.taml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml new file mode 100644 index 000000000..1a8665bbd --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.asset.taml @@ -0,0 +1,6 @@ + diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx new file mode 100644 index 000000000..3acc77e04 Binary files /dev/null and b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.fbx differ diff --git a/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript new file mode 100644 index 000000000..18269168b --- /dev/null +++ b/Templates/BaseGame/game/data/Prototyping/gui_offscreen_test/monitor_shape.tscript @@ -0,0 +1,61 @@ + +singleton TSShapeConstructor(monitor_shapefbx) +{ + baseShapeAsset = "Prototyping:monitor_shape"; + singleDetailSize = "0"; + neverImportMat = "DefaultMaterial ColorEffect*"; + flipUVCoords = "0"; + joinIdenticalVerts = "0"; + reverseWindingOrder = "0"; + removeRedundantMats = "0"; + animFPS = "2"; +}; + +function monitor_shapefbx::onLoad(%this) +{ + %this.addNode("Col-1", "", "0 0 0 0 0 1 0", "0", ""); + %this.addNode("ColBox-1", "Col-1", "0 0 0 1 0 0 0", "0", "Bounds"); + %this.addCollisionDetail("-1", "Box", "Bounds", "4", "10", "30", "32", "30", "30", "30", "Flood fill"); + %this.setBounds("-0.8 -0.244957 -0.0409516 0.8 0.244957 1.10231"); + + if (!isObject(screen_Canvas)) + { + new GuiOffscreenCanvas(screen_Canvas) { + targetName = "screen_Canvas"; + targetSize = "1280 720"; + dynamicTarget = false; + canInteract = true; + maxInteractDistance = "3"; + }; + } + + if(isObject(OptionsMenu)) + { + screen_Canvas.setContent(OptionsMenu); + } + + %screen_Canvas_asset = "Prototyping:ScreenTarget"; + if(!AssetDatabase.isDeclaredAsset(%screen_Canvas_asset)) + { + %screen_asset = new ImageAsset() + { + assetName = "ScreenTarget"; + versionId = 1; + imageFile = "#screen_Canvas"; + }; + TamlWrite(%screen_asset, expandPath("^Prototyping/gui_offscreen_test/" @ %screen_asset.AssetName @ ".asset.taml")); + %previewModule = ModuleDatabase.findModule("Prototyping",1); + AssetDatabase.addDeclaredAsset(%previewModule, expandPath("^Prototyping/gui_offscreen_test/" @ %screen_asset.AssetName @ ".asset.taml")); + } + + %mat_asset = "Prototyping:monitor_screen_mat"; + if(!AssetDatabase.isDeclaredAsset(%mat_asset)) + { + echo("Material asset not found, this should exist"); + } + + %assetDef = AssetDatabase.acquireAsset(%mat_asset); + %material = %assetDef.materialDefinitionName; + %material.DiffuseMapAsset = %screen_Canvas_asset; + +}