What is needed in this call to gdk_get_pixmap? - gtkmm

I have created a little drawing area class and now need a pixmap to draw into during the expose event callback. But I can't get any parameter that I have tried to compile. Here are the relevant parts of the code...
The class definition...
class set_display_drawing_area : public Gtk::DrawingArea
{
public:
set_display_drawing_area ();
virtual ~set_display_drawing_area ();
protected:
virtual bool on_expose_event(GdkEventExpose* event);
private:
GdkPixmap *pixmap_ptr;
};
and the expose callback...
bool set_display_drawing_area::on_expose_event(GdkEventExpose* event)
{
Glib::RefPtr<Gdk::Window> window = get_window();
if (window)
{
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
pixmap_ptr = gdk_pixmap_new (window, // <-- What is needed here?
width,
height,
-1);

You're mixing gtkmm (C++) and gtk (C) style code here. gdk_pixmap_new is a C function which has no idea about templates and classes (such as Glib::RefPtr). You'll probably want to use gtkmm for your pixmap as well:
Glib::RefPtr<Gdk::Pixmap> pixmap;
and
pixmap = Gdk::Pixmap::create(window, width, height);

Related

How to draw some text when click a button in wxWidgets?

I want to draw some text when click a button. My code is:
#include <wx/wx.h>
enum
{
BUTTON_Hello = wxID_HIGHEST + 1
};
class myFrame : public wxFrame {
public:
wxButton* HelloWorld;
wxPanel* panel;
void OnPaint(wxCommandEvent& event) {
wxClientDC bdc =wxClientDC(this);
bdc.DrawText(wxString("Draw some text when button clicked."), wxPoint(300, 300));
Refresh();
};
myFrame(wxWindow* parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize) :
wxFrame(parent,id,title, pos, size) {
panel =new wxPanel(this, wxID_ANY, wxPoint(0,0),wxSize(100,100));
//Connect(wxEVT_PAINT, wxPaintEventHandler(myFrame::OnPaint));
HelloWorld = new wxButton(panel, BUTTON_Hello, _T("Hello World"),
wxPoint(5,5), wxSize(100, 100));
HelloWorld->Bind(wxEVT_BUTTON, &myFrame::OnPaint, this);
};
};
class MyApp : public wxApp
{
bool OnInit() {
frame = new myFrame((wxFrame*)NULL, -1, wxT("Hello wxDC"),
wxPoint(50, 50), wxSize(800, 600));
frame->Show();
return true;
};
wxFrame* frame;
public:
};
IMPLEMENT_APP(MyApp)
I define the drawing function in a wxFrame and bind it to a wxButton using Bind(). The drawing function uses a wxClientDC. I have added Refersh() to force updating wxFrame. The wxButton belongs to a wxPanel which is a child of wxFrame.
However, when I click the button, nothing happens and no text is shown.
You must use wxPaintDC when drawing in your wxEVT_PAINT handler, not wxClientDC. While wxClientDC also "works", at least for now and at least under some platforms, this is definitely not the right way to do it.
When using wxPaintDC, Refresh() would work as expected and will result in a call to your paint handler during the next event loop iteration. Normally you don't need to call Update(), which immediately calls your handler, at all.
I solved this problem by myself.
As wxPanel is the only child of wxFrame, it will automatically cover the whole area of wxFrame. Now drawing on wxFrame is necessarily having no effect. So I have to draw on wxPanel:
void paintNow(wxCommandEvent& event) {
wxClientDC bdc =wxClientDC(panel);
bdc.DrawText(wxString("Draw some texts when button clicked."),
wxPoint(300, 300));
//panel->Refresh();
panel->Update();
};
Also I find that if I use Refresh() and Update() simultaneously, no text will be shown.
If I only use Refresh(), no text will be shown.

Making a highly customizable method, or a specific method that does a task?

I'm not really sure how I would phrase the title right, so I apologize for the initial confusion.
This is just a small question I had about how to structure code and such and I have no idea on what to call it so I will explain it with this example:
Say I am writing a Call of Duty type game where the player can customize their weapons with certain attachment.
I have a class that defines each gun. It looks something like this:
class Gun {
int clip = 30;
int ammo = 100;
float reloadTime = 5f;
float damage = 10f;
Attachment[] attachments;
//Plus some not included attachments.
void shoot() {
//...
}
void reload() {
//...
}
void applyAllAttachments() {
//Apply the list of attachments' effects
}
}
class Attachment {
void effect() {
//change the gun in some way.
}
}
Now I would like to add 4 attachments, Fast Mags (increase reload speed), Hollow Point (increase damage), Grenade Launcher (Secondary Gun) and Minigun (Replace the barrel with a minigun or something).
For the Fast Mags and the Hollow Point, it should be simple, all I have to do is change a number or a value, but for the Grenade Launcher and Minigun, which have custom, extra functions (like Unity Delegates), would it be wiser to add a function that handles external custom firing types, or would it be better to just have separate methods inside the Gun class that specifically handle to extra minigun functions?
TL;DR
If I want to add a grenade launcher attachment to a gun, should I do this:
class Gun {
int clip = 30;
int ammo = 100;
float reloadTime = 5f;
float damage = 10f;
Attachment[] attachments = Attachment[10];
//Plus some not included attachments.
void shoot() {
//...
customShoot();
}
void customShoot() {
//Apply attachments custom attachment shoot methods.
}
void reload() {
//...
}
void applyAllAttachments() {
//Apply the list of attachments' effects
}
}
class GrenadeLauncher extends Attachment {
#Override
public void effect() {
//Spawn new grenade
}
}
Or This:
class Gun {
int clip = 30;
int ammo = 100;
float reloadTime = 5f;
float damage = 10f;
Attachment[] attachments = Attachment[10];
//Plus some not included attachments.
void shoot() {
//...
if (attachments.GetType() == GrenadeLauncher) {
grenadeLauncherShoot();
}
}
void grenadeLauncherShoot() {
}
void reload() {
//...
}
void applyAllAttachments() {
//Apply the list of attachments' effects
}
}
Sorry for my pseudo/java code, hope it's comprehensible.
The first way is better: You can create new attachments without having to modify the Gun class.
In a general manner, you shouldn't need to check for type, and your code will be cleaner if you don't.
Here, your Attachment class should be abstract (I suppose it already is), and force children to implements some functions.
public abstract class Attachment
{
protected abstract void shoot();
}
Then the gun calls it for all Attachements:
class Gun {
int clip = 30;
int ammo = 100;
float reloadTime = 5f;
float damage = 10f;
Attachment[] attachments = Attachment[10];
//Plus some not included attachments.
void shoot() {
//...
for(int i = 0; i < attachments.length(); ++i) {
attachments[i].shoot();
}
}
void reload() {
//...
}
}
class GrenadeLauncher extends Attachment {
#Override
public void shoot()
{
//Spawn new grenade
}
}
By the way, why did you tag java and Unity? If you work with unity your code should be c# or javascript

LibGDX stage coordinates change on window resize

I have seen lots of topics on LibGDX and screen/cam coordinates and also some on window resizing, but I just can't find the solution to the following problem I have.
When making a basic stage and a basic actor in this stage, say windowsize 480x320, everything is OK. I can click my actor and it will respond. But when I resize my window, say to 600x320, everything looks right, but my clicklistener is not working anymore. Also, the stage coordinates are moved or messed up.
I use the following code:
stage.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
//determine if actor was hit
System.out.println(stage.hit(x, y, true));
return true;
}
});
Also, I am resizing my stage camera viewport to correspond to the window:
stage.getCamera().viewportWidth = Gdx.graphics.getWidth();
stage.getCamera().viewportHeight = Gdx.graphics.getHeight();
So when resizing, I get the desired effect on screen, but my listener does not respond - the actor seems 'offset' of where I am clicking. What am I doing wrong? Should I move my actor or my cam, or zoom my cam according to the resize? Can someone please explain this to me?
Thanks a lot in advance!
EDIT: below is the complete code of my class.
public class HelpMePlease implements ApplicationListener{
// A standard simple Actor Class
class CustomActor extends Actor {
Texture texture = new Texture(Gdx.files.internal("data/testTex2.png"));
TextureRegion pixelTexture = new TextureRegion(texture, 0, 0, 1, 1);
Sprite sprite = new Sprite(texture);
public CustomActor() {
setWidth(128);
setHeight(128);
setBounds(getX(), getY(), getWidth(), getHeight());
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
batch.draw(sprite, getX(), getY(), 0f, 0f, getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation());
}
}
public Stage stage;
public CustomActor actor;
#Override
public void create() {
stage = new Stage(480,320,true);
actor = new CustomActor();
stage.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
//determine if actor was hit
System.out.println(stage.hit(x, y, true));
return true;
}
});
Gdx.input.setInputProcessor(stage);
stage.addActor(actor);
}
#Override
public void resize(int width, int height) {
//resize cam viewport
stage.getCamera().viewportWidth = Gdx.graphics.getWidth();
stage.getCamera().viewportHeight = Gdx.graphics.getHeight();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
stage.getCamera().update(); //just to be sure, I don't know if this is necessary
stage.act();
stage.draw();
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
You can change your resize por this using the latest nightly.
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}
the last parameter "true" will center the camera in the screen
I think your actor is positioning itself good enough, but your display may be a bit off.
Try
batch.draw(sprite, getX(), getY(), 0f, 0f, getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation());
Instead of
batch.draw(sprite, getX(), getY(), getWidth(), getHeight(), 0f, 0f, getScaleX(), getScaleY(), getRotation());
Spritebatch has the following arguments:
public void draw (Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth,int srcHeight, boolean flipX, boolean flipY)
I guess you just mixed some arguments up by mistake, would you kindly take a look at it?
Problem solved by updating my LibGDX Version using Gradle and using the new Viewport options!
Thanks for taking the time everyone!
In my case adding
stage.getViewport().setScreenSize(width, height);
in resize() solved problem

Stage, viewport, camera, scaling, and Nexus 7

I am a newbies in Android and I am learning how to use libgdx as well. I found a few tutorials that use the “DisplayScreen extends AbstractScreen” coding technique, and they use Stage and Actor for displaying output. My interpretation of this coding technique is that DisplayScreen will use whatever in AbstractScreen unless it is #Override (please correct me if I am wrong).
Therefore, if I place the code in AbstractScreen resize() to scale the display to a bigger screen yet maintaining the aspect ratio; the stage in DisplayScreen should resize it to fit the bigger screen. The main objective is that I only want to concentrate my game development in 800x480 environment and completely ignore all different sizes/resolution. The resize() in AbstractScreen will do all the hard work to scale and fit my game to any resolution.
Please allow me to use my test example for better explanation. I have no problem displaying my 800x480 black background on my phone. However, the same background was displayed BUT not maintaining its aspect ratio on Nexus 7.
This turorial fixed my problem mentioned above (I adopted to have two black bars on both side of the screen). However, I have a small problem integrating this solution to the “DisplayScreen extends AbstractScreen” technique.
Please see this screen shot here. My issues are:
Why my black box is not resize to fit the screen, yet leaving two red bar on both sides of the screen?
I don’t understand why the black image only displaying 766x480 on my Nexus 7?
It will be fantastic if someone can point me to the right direction.
Code for awesomegame
package com.example.somegame;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.example.somegame.screens.DisplayScreen;
public class awesomegame extends Game {
public static AssetManager AssetManager = new AssetManager();
#Override
public void create() {
}
#Override
public void render() {
super.render();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
setScreen( new DisplayScreen(this) );
}
#Override
public void setScreen(Screen screen) {
super.setScreen( screen );
}
Code for AbstractScreen
package com.example.somegame.screens;
import com.example.somegame.awesomegame;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Scaling;
public class AbstractScreen implements Screen{
private awesomegame awesomegame;
private Stage stage;
private BitmapFont font;
private SpriteBatch batch;
private OrthographicCamera camera;
public AbstractScreen(awesomegame awesomegame) {
this.awesomegame = awesomegame;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
camera.update();
stage = new Stage(800, 480, false);
}
#Override
public void render(float delta) {
stage.act( delta );
Gdx.gl.glClearColor( .5f, .5f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
stage.draw();
}
#Override
public void resize(int width, int height) {
Vector2 size = Scaling.fit.apply(800, 480, width, height);
int viewportX = (int)(width - size.x) / 2;
int viewportY = (int)(height - size.y) / 2;
int viewportWidth = (int)size.x;
int viewportHeight = (int)size.y;
Gdx.gl.glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
stage.setViewport(800, 480, true);
}
Code for DisplayScreen
package com.example.somegame.screens;
import com.example.somegame.awesomegame;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
public class DisplayScreen extends AbstractScreen {
private Image loadingBg;
private Stage stage;
float loadingPercent;
public DisplayScreen(awesomegame awesomegame) {
super (awesomegame);
}
#Override
public void show()
{
super.show();
awesomegame.AssetManager.load("img/loading.atlas", TextureAtlas.class);
awesomegame.AssetManager.finishLoading();
stage = new Stage();
TextureAtlas atlas = awesomegame.AssetManager.get("img/loading.atlas", TextureAtlas.class);
loadingBg = new Image(atlas.findRegion("loadingBg"));
loadingBg.setSize(800, 480);
loadingBg.setX(0);
loadingBg.setY(0);
stage.addActor(loadingBg);
// add all asset need to be loaded here. for example
// awesomegame.AssetManager.load("img/whatever.pack", TextureAtlas.class);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor( 1f, 0f, 0f, 1f );
stage.draw();
}
The Nexus 7 has a screen resolution of 1280 x 800, but part of the height is used for the onscreen menu panel (with the back/home/menu buttons).
The main culprit in your code is here, where you try to enforce a specific aspect ratio that doesn't fit this adjusted dimension, resulting in those bars on the side:
public void resize(int width, int height) {
Vector2 size = Scaling.fit.apply(800, 480, width, height);
...
}
Looks like you pulled that resize function off another stackoverflow post. I had done the same, but switched to something simpler when i ran into the same issue:
public void resize(int width, int height) {
stage.setViewport(true, width,height);
stage.getCamera().setToOrtho(false,width,height);
...
}
This code works for me with the latest update:
OrthographicCamera is cam, this makes no cropping, just changes the viewport so the width is still "that many" times larger than the actual window/device
public void resize(int width, int height) {
int newW = width, newH = height;
if (cam.viewportWidth > width) {
float scale = (float) cam.viewportWidth / (float) width;
newW *= scale;
newH *= scale;
}
// true here to flip the Y-axis
cam.setToOrtho(true, newW, newH);
}

MapPoint GetPictureFromObject method

According to the msdn documentation:
GetPictureFromObject method
Returns a picture (Visual Basic Picture object) of the current map view.
After digging around, I found that this "Picture" object apparently hasn't existed since VB6. I guess there's no way to write a class to masquerade as this type... Or is there?
It seems that this is a problem with no pretty solution.
public Image GetImage()
{
Image image = null;
object save = Clipboard.GetDataObject();
try
{
Application.ActiveMap.CopyMap();
IDataObject pict = Clipboard.GetDataObject();
string[] formats = pict.GetFormats();
foreach (string s in formats)
{
if (s.EndsWith(System.Windows.Forms.DataFormats.Bitmap))
{
image = (System.Drawing.Image)pict.GetData(System.Windows.Forms.DataFormats.Bitmap);
break;
}
}
}
finally
{
Clipboard.SetDataObject(save);
}
return image;
}
The GetPictureFromObject() method returns a stdole.IPictureDisp COM object.
Here is a working example from http://www.mapping-tools.com/howto/mappoint/programming/creating-map-images-in-c/
// Find the size of the PictureBox in pixels
// Then convert it into HIMETRIC units for MapPoint
// We perform the conversion using Inch2HIMETRIC (see above) and
// the system DPI values
// Note: MapPoint/VB6's definition of "long" is the same as C#'s definition for "int".
int iWidth, iHeight;
Graphics g = myPictureBox.CreateGraphics();
iWidth = (int)((double)myPictureBox.Width * Inch2HIMETRIC / g.DpiX);
iHeight = (int)((double)myPictureBox.Height * Inch2HIMETRIC / g.DpiY);
// GetPictureFromObject() is defined as a member of the MapPointUtilities class
MapPoint.MapPointUtilities myMapUtils = new MapPoint.MapPointUtilities();
// Create the Picture for the current map, as an stdole.IPictureDisp COM object
stdole.IPictureDisp ipicMap = (stdole.IPictureDisp)myMapUtils.GetPictureFromObject(myMap, iWidth, iHeight);
// Convert it to a (metafile) Drawing.Image using the OleCreateConverter defined above
System.Drawing.Image myImage = OleCreateConverter.PictureDispToImage(ipicMap);
// Copy the Drawing.Image to the Picture box
// Refresh and stretch for good measure
myPictureBox.Image = myImage;
myPictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
myPictureBox.Refresh();
// Save it as a PNG
// Although a GIF is capable of holding a MapPoint map, PNGs are generally prefered
myImage.Save(#"london2012.png", System.Drawing.Imaging.ImageFormat.Png);
Here is the metadata from stdole.dll:
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace stdole
{
[InterfaceType(2)]
[Guid("7BF80981-BF32-101A-8BBB-00AA00300CAB")]
[ComConversionLoss]
public interface IPictureDisp
{
[DispId(0)]
[ComAliasName("stdole.OLE_HANDLE")]
int Handle { get; }
[DispId(5)]
[ComAliasName("stdole.OLE_YSIZE_HIMETRIC")]
int Height { get; }
[DispId(2)]
[ComAliasName("stdole.OLE_HANDLE")]
int hPal { get; set; }
[DispId(3)]
short Type { get; }
[DispId(4)]
[ComAliasName("stdole.OLE_XSIZE_HIMETRIC")]
int Width { get; }
[DispId(6)]
void Render(int hdc, int x, int y, int cx, int cy, int xSrc, int ySrc, int cxSrc, int cySrc, IntPtr prcWBounds);
}
}