Can't assign the landscape LayerInfo object to a landscape - c++

I've been developing an automated system that requires me to generate the LayerInfo objects of a given Landscape. So far I've been able to generate the required LayerInfo object's, but I wasn't able to assign them, or to be more precise, when I try to assign the necessary layers in the ULandscapeInfo property they appear in the editor but are not assigned, unless I save them and restart the engine, they also appear weird in the editor, as you can see in the image. I think it's a similar problem to the one in this thread. The code bellow it's responsible for assignig the LayerInfo:
// This method creates a
// new layer info object
UWorld * currentWorld = GetWorld();
ULevel * level = currentWorld->GetLevel(0); // TODO : just for debuging
ULandscapeLayerInfoObject* layerInfo = Landscape->CreateLayerInfo(*(layerName), level);
bool isDirty = layerInfo->MarkPackageDirty();
// Get a reference for the landscape Info
ULandscapeInfo* landscapeInfo = Landscape->GetLandscapeInfo();
landscapeInfo->CreateLayerEditorSettingsFor(layerInfo);
FLandscapeInfoLayerSettings* layerSettings = &landscapeInfo->Layers[1];
landscapeInfo->Layers[0] = FLandscapeInfoLayerSettings(layerInfo, Landscape);
UEditorAssetLibrary::SaveAsset(assetName, false);
// Assign the respective values
if (!layerSettings->LayerInfoObj)
{
layerSettings->Owner = Landscape;
layerSettings->LayerInfoObj = layerInfo;
layerSettings->bValid = true;
}
Editor Screenshot

Related

Error when dynamically creating more than one Frame at runtime (C++, FMX, IDE: C++ Builder)

I would like to dynamically create a series of Frame components, then save the pointers into a vector.
I am able to dynamically create TEdit components with no problem, but if I replace TEdit with the name of the frame component (that contains an edit box) the program will error. The first frame will be created, but errors when creating the second one, stating "External exception EEFFACE"
Here is the relevant code. Note that if I replace TFrame2 with TEdit, it works.
class TForm1 : public TForm
{
...
public: // User declarations
std::vector<TFrame2*> fields;
...
};
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFrame2* temp = new TFrame2 (Layout1);
temp->Parent = Layout1;
temp->Align = TAlignLayout::Top;
fields.push_back(temp);
count++;
}
This is what it looks like after one click.
Error message after 2 clicks.
This is how I want it to look after two clicks.
This is what it looks like when I replace TFrame2 with TEdit, after 3 clicks.
-
EDIT
If I try to hard-code the creation of two Frames, I get the same error on the first click.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TFrame2* temp = new TFrame2 (Layout1);
temp->Parent = Layout1;
temp->Align = TAlignLayout::Top;
fields.push_back(temp);
count++;
TFrame2* temp1 = new TFrame2 (Layout1);
temp1->Parent = Layout1;
temp1->Align = TAlignLayout::Top;
fields.push_back(temp1);
count++;
}
-
EDIT 2
In this post
Can FireMonkey frames be created dynamically?
I see a comment that states
I should note here that it seems the frame objects need to be assigned a unique Name property manually right after creation, at least when using C++, or the next frame object created of the same type will try to take the same name as the first one.
To fix this issue, I needed to set the name of the Frame at runtime. Adding the following code in the Button1 click method fixes the issue.
temp->Name = std::strcat("TFrame2", std::to_string(count).c_str());
This names every new Frame "TFrame2#" where # is the number frame that has been created.

C++ MFC MDI data as Document not on disk [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I would like to use MFC MDI but my data (Document) is not on the disk.
I have functions that generate data according to the input.
Data of type A, type B etc.
I would like to open a new tab for every new data generated.
For example, if the input of the generated data is X, I would like to open a new tab with the name X on it. If the X exists, I would like to activate (bring front) the X tab as the MDI already does.
My idea is to have multiple CMultiDocTemplate. Each one generated by different CDocument/CView derived class.
I am looking for a solution to overload the open/new function so instead of opening a file from disk, ask from my functions to generate the data (CDocument).
Also, I don't want the user to choose between CMultiDocTemplate/Cview but I want to choose which one to use for the new tab.
I am not sure if this is what you might be looking for, but I used code like this to change the view to a different one based on the document being loaded:
BOOL CCommunityTalksDoc::SwitchToView(CRuntimeClass* pNewViewClass)
{
POSITION rPos;
CView *pOldActiveView;
CFrameWnd *pChild;
CCreateContext context;
BOOL bAutoDelete;
rPos = GetFirstViewPosition();
pOldActiveView = GetNextView(rPos);
pChild = pOldActiveView->GetParentFrame();
// If we're already displaying this kind of view, no need to go further.
if (pOldActiveView->IsKindOf(pNewViewClass))
return TRUE;
// Set flag so that document will not be deleted when view is destroyed.
bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE;
// Delete existing view
pOldActiveView->DestroyWindow();
// restore flag
m_bAutoDelete = bAutoDelete;
// Create new view.
m_pScriptView = (CScriptParseView*)pNewViewClass->CreateObject();
if (m_pScriptView == nullptr)
{
TRACE1("Warning: Dynamic create of view type %s failed\n", pNewViewClass->m_lpszClassName);
return FALSE;
}
// we must ensure the popup dialogues don't display
m_pScriptView->SetBuildMode(FALSE);
// Draw new view.
context.m_pNewViewClass = pNewViewClass;
context.m_pCurrentDoc = this;
context.m_pNewDocTemplate = nullptr;
context.m_pLastView = nullptr;
context.m_pCurrentFrame = pChild;
if (!m_pScriptView->Create(nullptr, nullptr, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0),
pChild, AFX_IDW_PANE_FIRST, &context))
{
TRACE0("Warning: couldn't create view for frame\n");
delete m_pScriptView;
m_pScriptView = nullptr;
return FALSE;
}
m_pScriptView->SendMessage(WM_INITIALUPDATE, 0, 0); // WM_INITIALUPDATE is defined in afxpriv.h
pChild->RecalcLayout();
m_pScriptView->UpdateWindow();
pChild->SetActiveView(m_pScriptView);
return TRUE;
}
You use it like:
CRuntimeClass *pNewViewClass = RUNTIME_CLASS(CScriptParseView);
if (!SwitchToView(pNewViewClass))
{
// fail, don't know why it would fail
ASSERT(FALSE);
}

GetCompatibleComponent returning a Vector Error

I'm creating a Basic Button event for a University Project and I'm having problems trying to access an Entity's child.
I am using a Component model in order to create and display all objects on the screen and one "button" is comprised of 3 separate components, a TextComponent that displays what the button does i.e. "Start Game", a SpriteComponent that creates and displays an image above the text, and a ShapeComponent that acts as a "Bounding Box" for my button. This component functions purely as a sort of Event Handler, checking to see if the mouse is inside the shape's bounding box and if so, allows the user to interact with it (like display a message).
Below is the code for one of my buttons.
static shared_ptr<Entity> btnStartGame;
void MainMenuScene::Load() {
//START GAME BUTTON
auto txtNewGame = makeEntity();
auto t = txtNewGame->addComponent<TextComponent>("New Game");
t->getText().setOrigin(t->getText().getGlobalBounds().width / 2, t->getText().getGlobalBounds().height / 2);
txtNewGame->setPosition(Vector2f(280.f, 500.f));
auto sword = makeEntity();
auto s = sword->addComponent<SpriteComponent>();
s->Sprite("Sword.png", IntRect(0, 0, 60, 60));
sword->setPosition(Vector2f(370.f, 540.f));
auto btnStartGame = makeEntity();
auto b = btnStartGame->addComponent<ShapeComponent>();
b->setShape<sf::RectangleShape>(Vector2f(200.f, 105.f));
b->getShape().setFillColor(Color(224, 190, 20)); //just so I can see where it is
b->getShape().setOrigin(b->getShape().getGlobalBounds().width / 2, b->getShape().getGlobalBounds().height / 2);
btnStartGame->setPosition(Vector2f(Engine::GetWindow().getSize().x / 4 - 40.f, 525.f));
}
Once the Bounding box is created, I do a validation check in the Update function in order to see if the mouse is currently inside the ShapeComponent's bounding box. I get the component of the btnStartGame Entity and get it's GlobalBounds, after this is done, I check to see if the mouse is currently inside the box However this line causes an error.
if (btnStartGame->get_components<ShapeComponent>()[0]->getShape().getGlobalBounds().contains(Engine::GetWindow().mapPixelToCoords(sf::Mouse::getPosition())))
{
cout << "level 1 selected" << endl;
}
I get a Read Access Violation Error at this line in Vector
pointer _Unchecked_begin() _NOEXCEPT
{ // return pointer for beginning of mutable sequence
return (this->_Myfirst());
}
Does anyone know why this is happening? I thought at first it was a pointer error but that didn't seem to fix anything.
Solved the problem.
I had created a shared_ptr and instead of referencing the Entity I had created, I was trying to point to a new one inside the Load() function.
Removing the Auto from btnStartGame solved the issue
btnStartGame = makeEntity();

When exactly are published properties assigned at run time?

I have a custom control which needs to do some things when loading at run time, based on a published property. However, I am running into a problem where, whenever I check the published property, it has not been set yet, and is always the default value.
I first attempted checking the property in the constructor, of the control, but quickly found they were not loaded yet. I know that when the control is shown on the screen the properties are set correctly, thus its not an issue with the properties not being loaded at all.
I next attempted overriding the Loaded Method but am still having the same problem, so I don't think this is exactly what I am looking for.
void __fastcall TFmSearchBar::Loaded()
{
TEdit::Loaded(); //call base class loaded
if( MyProperty )
{
//do stuff
}
}
At what point are these published properties actually getting set?
What method can/should I hook into in order to execute some logic in my control based on these properties, as soon as the properties are set correctly?
If I check the property in the constructor of the control, the property is always the default value even if I have specified otherwise in the designer.
Correct, because its design-time values have not been assigned yet.
At what point are these published properties actually getting set?
When the Owner (Form, Frame, or DataModule) is being constructed. It loads its own DFM resource and parses it, constructing stored child components and reading their property values.
For example, say you have the following DFM:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
...
object Edit1: TEdit
Left = 136
Top = 64
Width = 121
Height = 21
TabOrder = 0
end
object Button1: TButton
Left = 263
Top = 62
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 1
end
end
The DFM streaming process roughly translates to the following equivalent code (I'm leaving a lot of internal details out for simplicity):
__fastcall TCustomForm::TCustomForm(TComponent *Owner)
: TScrollingWinControl(Owner)
{
this->FFormState << fsCreating;
try
{
// locate, load, and parse the "Form1" DFM resource ...
this->FComponentState << csLoading;
this->Parent = ...;
this->Name = L"Form1":
this->FComponentState << csReading;
this->Left = 0;
this->Top = 0;
this->Caption = L"Form1";
...
TEdit *e = new TEdit(this);
try
{
e->FComponentState << csLoading;
e->Parent = this;
e->Name = L"Edit1"; // <-- sets the derived Form's 'Edit1' member to this object
e->FComponentState << csReading;
e->Left = 136;
e->Top = 64;
e->Width = 121;
e->Height = 21;
e->TabOrder = 0;
e->FComponentState >> csReading;
}
catch (...)
{
delete e;
throw;
}
TButton *b = new TButton(this);
try
{
b->FComponentState << csLoading;
b->Parent = this;
b->Name = L"Button1"; // <-- sets the derived Form's 'Button1' member to this object
b->FComponentState << csReading;
b->Left = 263;
b->Top = 62;
b->Width = 75;
b->Height = 25;
b->Caption = L"Button1";
b->TabOrder = 1;
b->FComponentState >> csReading;
}
catch (...)
{
delete b;
throw;
}
this->FComponentState >> csReading;
...
e->Loaded();
b->Loaded();
this->Loaded();
}
__finally
{
this->FFormState >> fsCreating;
}
}
So, as you can see, a component's property values are not available yet when its constructor is called.
What method can/should I hook into in order to execute some logic in my control based on these properties, as soon as the properties are set correctly?
That depends on what the properties need to do. If they need to perform operations immediately, you can do that directly in their property setters. But if they need to wait until other properties have been loaded first (if one property is dependent on the value of another property), then override the virtual Loaded() method instead, which is automatically called after DFM streaming is finished. Property setters can check the flags of the ComponentState property to know whether or not the component is currently running in the Form Designer at design-time, whether or not a DFM is currently being streamed, etc and then act accordingly as needed.
I attempted overriding the Loaded Method but am still having the same problem
Which is what exactly? You did not explain what your actual problem is. Please edit your question to provide those details.
so I don't think this is exactly what I am looking for.
It most likely is, you probably are just not using it correctly.

MFC - Printing - Changing page orientation from a custom pagesetup dialog

I am developing a custom print dialog and page setup using MFC and VS2008 for my Win32 program. Since the code is legacy, I can't take much advantage from MFC view/doc architecture. As a result, I wrote a printing code completely from scratch.
I setup CPrintInfo, instantiate my custom print dialog box and hook this dialog box to the CPrintInfo I just created. When my custom print dialog is up, I have a radio button to let a user toggles the page orientation. For some reasons, I couldn't modify the current DEVMODE at the run-time. As a result, every page I print will end up as a portrait.
Even if I manually set pDevMode->dmOrientation to DMORIENT_LANDSCAPE from the event handler of the custom print dialog, the printing result is still ended up as portrait. I am really not sure why this is happening and how to modify the DevMode after the print dialog is up.
Thank you in advance for any help.
Here is the code I have:
void PrintSomething(CWnd* currentWnd) {
// Create CPrintInfo
CPrintInfo* pPrintInfo = new CPrintInfo;
SetupPrintInfo(pPrintInfo); // simply setup some member variables of CPrintInfo
// Create a custom print dialog
CustomPrintDlg* pCustomPrtDlg = new CustomPrintDlg(FALSE, PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS
| PD_HIDEPRINTTOFILE | PD_NOSELECTION, pPrintInfo, currentWnd);
SetupPrintDialog(pPrintInfo,pCustomPrtDlg);
if ( AfxGetApp()->DoPrintDialog(pCustomPrtDlg) == IDOK ) {
... // proceed a print loop
}
}
Code for setting up the custom print dialog:
void SetupPrintDialog(CPrintInfo* pPrintInfo,CustomPrintDlg* pCustomPrtDlg) {
delete pInfo->m_pPD;
pInfo->m_pPD = pCustomPrtDlg;
pInfo->m_pPD->m_pd.hInstance = AfxGetInstanceHandle();
pInfo->m_pPD->m_pd.lpPrintTemplateName = MAKEINTRESOURCE(IDD_CUSTOM_PRTDLG);
// Set the Flags of the PRINTDLG structure as shown, else the
// changes will have no effect.
pInfo>m_pPD->m_pd.Flags |= PD_ENABLEPRINTTEMPLATE;
// Set the page range.
pInfo>m_pPD->m_pd.nMinPage = 1; // one based page numbers.
pInfo>m_pPD->m_pd.nMaxPage = 0xffff; // how many pages is unknown.
}
When a user toggles the radio button to Landscape, this function will be invoked:
void CustomPrintDlg::OnLandscapeChecked() {
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalUnlock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
}
A pseucode for the custom print dialog class:
class CustomPrintDlg: public CPrintDialog {
... // just override some methods from CPrintDialog
};
Thanks again,
Unagi
I figured out the solution:
All I need is to call GlobalLock to obtain a pointer to the Devmode before changing the current DevMode.
void CustomPrintDlg::OnLandscapeChecked()
{
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalLock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
GlobalUnlock(pDevMode)
}
Thanks again for helping me.
Nowhere in your example code do you show how you're creating the DC for printing. When you call CreateDC, you must pass a pointer to a DEVMODE structure; this defines whether the printing will be portrait or landscape.