EDIT: by not working I mean that in my main array mA in main doesn't show any change to the elements within the array.
I have been checking my functions as I develop the headers and they have been working perfectly: Until I got to the final header MonitorArray.h.
mA.getScreen(i).checkScreen();
Didn't work and I couldn't work out why. So I created a new function within MonitorArray to do a similar job using the same function, and to my surprise it worked.
mA.pollScreens();
Which uses (Inside MonitorArray.h):
monitorArray[i].checkScreen();
Function getScreen:
ScreenArray MonitorArray::getScreen(int arrayPointer)
{
if (arrayPointer<0 || arrayPointer>=monitors)
{
return false;
}
else
{
return monitorArray[arrayPointer];
}
}
Function checkScreen and addArray:
void ScreenArray::checkScreen()
{
HDC dMonitor;
PixelArray pArray;
int lenX = 0, lenY = 0;
dMonitor = CreateDC(iMonitor.szDevice, iMonitor.szDevice, NULL, NULL);
lenX = (iMonitor.rcWork.right - iMonitor.rcWork.left) - 1;
lenY = (iMonitor.rcWork.bottom - iMonitor.rcWork.top) - 1;
pArray.setColour(0, GetPixel(dMonitor, 0, 0));
pArray...
...
...
addArray(&pArray);
ReleaseDC(NULL, dMonitor);
}
void ScreenArray::addArray(PixelArray* pA)
{
if (previousCheck(*pA))
{
arrayPosition = 0;
screenArray[arrayPosition] = *pA;
arrayPosition++;
}
else
{
screenArray[arrayPosition] = *pA;
arrayPosition++;
}
if (arrayPosition==11)
{
//Run screen saver on monitor
}
}
Why does running the command within the header file through a new function work but running the functions from main not?
Assuming that "didn't work" means "didn't affect the ScreenArray in my MonitorArray", it's because getScreen returns a copy of the array element
ScreenArray MonitorArray::getScreen(int arrayPointer)
while the new member function most likely works with the array directly.
You'll need to return a pointer to the array element instead:
ScreenArray* MonitorArray::getScreen(int arrayPointer)
{
if (arrayPointer<0 || arrayPointer>=monitors)
{
return NULL;
}
else
{
return &monitorArray[arrayPointer];
}
}
(BTW: the implicit conversion from bool to ScreenArray looks very odd.)
Related
I'm new(-ish) to C++, and I'm trying to learn something new every day. Today I'm trying to figure this out.
Do I have to check if Valmis == 1 so it won't continue/return before Realtest() is complete?
This is just an example.
int valmis = 0;
void test::Main()
{
//just some basic stuff
do
{
if (!strcmp())
{
//here too
float testing = 0;
printf("Test? 1=do it Else=Nothing\n");
scanf(" %f", &testing);
if (testing == 1)
{
Realtest();
//Realtest needs to be completed before continuing
if (valmis == 1) //Do I need this or does it continue after RealTest() is complete without this?
return (somethingmate = true);
}
else
{
return (somethingmate = true);
}
}
} while();
return (somethingmate = false);
}
void test::Realtest()
{
//doing something here that I need to do before continuing in main/letting somethingmate to become true
valmis = 1; //do i need this?
}
I am new to C++. I've wrote code in C# and PHP.Since I am using Unreal engine I am trying to learn C++. For my project I need to make a screenshot in-game and show it immediately so I want to get it as a texture.
I made a blueprint node which calls this function i've made:
void UMyBlueprintFunctionLibrary::TakeScreenshot()
{
FScreenshotRequest::RequestScreenshot(true);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "Tried to take screenshot");
}
When I hover my mouse above RequestScreenshot I see the following pop-up:
"Screenshot can be read from memory by subscribing to the viewsport OnScreenshopCaptured delegate"
So that is what I try to do but I have no idea how I looked up this:
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UGameViewportClient/OnScreenshotCaptured/
Can someone tell me how to implement this and how you see/know how to implement it?
I have an alternative, no delegate, but FRenderTarget::ReadPixel() to some buffer you allocated, by implementing your own UGameViewportClient (inherit it), and overriding Draw() function.
I'll show the essential codes, but not complete.
void UMyGameViewportClient::Draw(FViewport* Viewport, FCanvas* SceneCanvas)
{
Super::Draw(Viewport, SceneCanvas);
if (any_condition_you_need) {
CaptureFrame();
}
}
void UMyGameViewportClient::CaptureFrame()
{
if (!Viewport) {
return;
}
if (ViewportSize.X == 0 || ViewportSize.Y == 0) {
return;
}
ColorBuffer.Empty(); // Declare this in header as TArray<FColor>
if (!Viewport->ReadPixels(ColorBuffer, FReadSurfaceDataFlags(),
FIntRect(0, 0, ViewportSize.X, ViewportSize.Y)))
{
return;
}
SaveThumbnailImage();
}
void UMyGameViewportClient::SaveThumbnailImage()
{
IImageWrapperModule& wrappermodule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
auto wrapper_ptr = wrappermodule.CreateImageWrapper(EImageFormat::PNG);
for (int i = 0; i < ColorBuffer.Num(); i++)
{
auto ptr = &ColorBuffer[i];
auto r = ptr->R;
auto b = ptr->B;
ptr->R = b;
ptr->B = r;
ptr->A = 255;
} // not necessary, if you like bgra, just change the following function argument to ERGBFormat::BGRA
wrapper_ptr->SetRaw(&ColorBuffer[0], ColorBuffer.Num() * 4,
ViewportSize.X, ViewportSize.Y, ERGBFormat::RGBA, 8);
FFileHelper::SaveArrayToFile(wrapper_ptr->GetCompressed(), *ThumbnailFile);
}
I'm having some trouble with the following method and I need some help trying to figure out what I am doing wrong.
I want to return a reference to a Value in a document. I am passing the Document from outside the function so that when I read a json file into it I don't "lose it".
const rapidjson::Value& CTestManager::GetOperations(rapidjson::Document& document)
{
const Value Null(kObjectType);
if (m_Tests.empty())
return Null;
if (m_current > m_Tests.size() - 1)
return Null;
Test& the_test = m_Tests[m_current];
CMyFile fp(the_test.file.c_str()); // non-Windows use "r"
if (!fp.is_open())
return Null;
u32 operations_count = 0;
CFileBuffer json(fp);
FileReadStream is(fp.native_handle(), json, json.size());
if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError())
{
(...)
}
else
{
if (!document.IsObject())
{
(...)
}
else
{
auto tests = document.FindMember("td_tests");
if (tests != document.MemberEnd())
{
for (SizeType i = 0; i < tests->value.Size(); i++)
{
const Value& test = tests->value[i];
if (test["id"].GetInt() == the_test.id)
{
auto it = test.FindMember("operations");
if (it != test.MemberEnd())
{
//return it->value; is this legitimate?
return test["operations"];
}
return Null;
}
}
}
}
}
return Null;
}
Which I am calling like this:
Document document;
auto operations = TestManager().GetOperations(document);
When I inspect the value of test["operations"] inside the function I can see everything I would expect (debug code removed from the abode code).
When I inspect the returned value outside the function I can see that it's an array (which I expect). the member count int the array is correct as well, but when print it out, I only see garbage instead.
When I "print" the Value to a string inside the methods, I get what I expect (i.e. a well formated json), but when I do it outside all keys show up as "IIIIIIII" and values that aren't strings show up correctly.
rapidjson::StringBuffer strbuf2;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer2(strbuf2);
ops->Accept(writer2);
As this didn't work I decided to change the method to receive a Value as a parameter and do a deep copy into it like this
u32 CTestManager::GetOperationsEx(rapidjson::Document& document, rapidjson::Value& operations)
{
(...)
if (document.ParseInsitu<kParseCommentsFlag>(json).HasParseError())
{
(...)
}
else
{
if (!document.IsObject())
{
(...)
}
else
{
auto tests = document.FindMember("tests");
if (tests != document.MemberEnd())
{
for (SizeType i = 0; i < tests->value.Size(); i++)
{
const Value& test = tests->value[i];
if (test["id"].GetInt() == the_test.id)
{
const Value& opv = test["operations"];
Document::AllocatorType& allocator = document.GetAllocator();
operations.CopyFrom(opv, allocator); //would Swap work?
return operations.Size();
}
}
}
}
}
return 0;
}
Which I'm calling like this:
Document document;
Value operations(kObjectType);
u32 count = TestManager().GetOperationsEx(document, operations);
But... I get same thing!!!!
I know that it's going to be something silly but I can't put my hands on it!
Any ideas?
The problem in this case lies with the use of ParseInSitu. When any of the GetOperations exist the CFileBuffer loses scope and is cleaned up. Because the json is being parsed in-situ when the buffer to the file goes, so goes the data.
I have a sfml window container, and it appears to be working, however the glViewPorts are the wrong size, which I assume is because the wrong sf::Window is being passed.
Here is a function which adds to the window: It takes some information about the sfml window.
int WindowContainer::PushBack(WindowData& data)
{
if(data.WindowSettingsOK() && data.VideoModeOK()){
mWindowVector.resize(mWindowVector.size() + 1);
mDisplayFuncVector.resize(mWindowVector.size());
mInputFuncVector.resize(mWindowVector.size());
mWindowVector.at(mWindowVector.size() - 1) = new sf::Window();
mWindowVector.at(mWindowVector.size() - 1)->Create(data.VideoMode(), data.Title(), data.Style(), data.Settings());
mWindowVector.at(mWindowVector.size() - 1)->SetPosition(data.PositionX(), data.PositionY());
mDisplayFuncVector.at(mWindowVector.size() - 1) = nullptr;
mInputFuncVector.at(mWindowVector.size() - 1) = nullptr;
return 0;
}
else{
PrintError(ErrorMessageType::BadSettings);
return 1;
}
}
Alternatively, this function may be called to setup the display and input function callbacks:
int WindowContainer::PushBack(WindowData& data, function_p displayFunc, function_p inputFunc)
{
int return_val = PushBack(data);
mDisplayFuncVector.at(mWindowVector.size() - 1) = displayFunc;
mInputFuncVector.at(mWindowVector.size() - 1) = inputFunc;
return return_val;
}
Then, when the window needs .Display()'ing, this function is called:
void WindowContainer::ProcessDisplay()
{
for(unsigned int i = 0; i < mWindowVector.size(); i ++){
if(mDisplayFuncVector.at(i) != nullptr){
mDisplayFuncVector.at(i)(*mWindowVector.at(i), mClock, (const void*&)mExternalDrawingDataPointer);
}
mWindowVector.at(i)->Display();
}
}
... This is all good, until the result on the screen is that resizing one window affects the viewport of both windows. This suggests that calling the callback function: mDisplayFuncVector.at(i)(*mWindowVector.at(i), mClock, (const void*&)mExternalDrawingDataPointer); gives the argument of *mWindowVector.at(0) each time, instead of each window individually. (As in *mWindowVector.at(i))
Can anyone help with this problem?
The main loop contains this code:
while(container.Access(0)->IsOpened()){
container.ProcessInput();
container.ProcessDisplay();
}
Container.Access(int) is this function:
const sf::Window*& WindowContainer::Access(unsigned int index)
{
if(index > mWindowVector.size()){
PrintError(ErrorMessageType::IndexOutOfRange);
}
else{
return (const sf::Window*&)mWindowVector.at(index);
}
return (const sf::Window*&)mWindowVector.at(0);
}
Thanks again, I'm sure I have made a mistake somewhere but cannot spot it.
I have been thinking about this question and suspect openGL becomes confused with which window is it drawing to if more than one object is pushed back without a call to Display() to sync everything.
I am yet to test this and confirm.
EDIT The window container now works. It has nothing to do with the callback functions argument.
Ive been staring at my code and I can't figure out why on earth my constructor is not gettign called.
It's just ignoring my constructor completely (i've check with stepping with debugger).
Here's my testapp:
using namespace MyEngine;
int _tmain(int argc, _TCHAR* argv[])
{
TestManager* testMgr = new TestManager();
testMgr->RunAllTests();
delete testMgr;
getchar();
return 0;
}
TestManager.h:
namespace MyEngine
{
class TestManager
{
public:
TestManager();
TestManager(uint64_t RepeatTimes);
~TestManager();
bool RunAllTests();
bool RunMemoryTests();
private:
Engine* mEngine;
ILogManager* mLogger;
MemoryTestManager* mMemTestMgr;
uint64_t mRepeatTimes;
};
}
and TestManager.cpp
namespace MyEngine
{
TestManager::TestManager()
{
TestManager(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
TestManager::~TestManager()
{
}
/* Runs all testing modules */
bool TestManager::RunAllTests()
{
bool res = true;
/* Init Engine */
if(mEngine->Init(0,0,0))
{
res = true;
res && mEngine->GetRenderManager()->Init();
res && mLogger->Init(true,true);
res && mEngine->GetMemoryManager()->Init(false);
}
else
return false;
/* Start Engine */
mEngine->Start();
/* Get logger */
mLogger = mEngine->GetLogger();
/* Run Memory Tests */
res &= RunMemoryTests();
if (res)
mLogger->LogInfo("TEST: TESTING SUCCESSFULL");
else
mLogger->LogError("TEST: TESTING FAILED");
return res;
}
/* Runs all memory tests */
bool TestManager::RunMemoryTests()
{
bool res = true;
res &= mMemTestMgr->AllocateTest();
res &= mMemTestMgr->ReferenceTest();
if (res)
mLogger->LogInfo("TEST: RunMemoryTests SUCCESSFULL");
else
mLogger->LogError("TEST: RunMemoryTests FAILED");
return res;
}
}
You cant call another constructor from the same class. I'd refactor the init code into a separate method and call it from both constructors:
namespace MyEngine
{
TestManager::TestManager()
{
Init(1);
}
TestManager::TestManager(uint64_t RepeatTimes)
{
Init(RepeatTimes);
}
void TestManager::Init(uint64_t RepeatTimes)
{
if (RepeatTimes>0)
mRepeatTimes = RepeatTimes;
else
{
mRepeatTimes = 1;
}
mEngine = Engine::GetEngine();
mMemTestMgr = new MemoryTestManager();
}
}
When you call TestManager(1); inside your TestManager::TestManager() constructor, you're creating another instance of TestManager, using the constructor TestManager::TestManager(uint64_t).
You can't do this on C++, you have to create either a init method, were you set the instance variables to whatever you want, or use optional parameters:
TestManager(uint64_t RepeatTimes = 0);
Then, if you create an instance of TestManager without arguments, you will be calling the TestManager::TestManager(uint64_t)constructor with 0 as the uint64_t argument.
you can't call a default constructor from a overloaded constructor. Why don't you simply create you object like this:
TestManager* testMgr = new TestManager(1);
Using a default argument (as per fontanini's answer) will do what you want in this case.
But if this is a simplified example and you really do want to delegate to another constructor, then that's not possible in C++03 - the line TestManager(1) just constructs a temporary object which goes unused (and the line will probably be optimized out unless the TestManager(uint64_t) constructor has side effects).
However, you can do what you're aiming for here with a C++11 compiler and the following syntax:
TestManager::TestManager() :
TestManager(1)
{
}