Maya C++ plugin access to imageFile loaded on the current imagePlane - c++

I am writing a Maya C++ plugin that needs to get access to the imageFile that is loaded in the current imagePlane. I've got the plugin written, and I am able to iterate successfully through the imagePlanes, but I don't know how to get the imageFile that is loaded on the imagePlane. I have written a plugin that has a callback for the scene being loaded, and I'm that successfully iterateing through the imagePlanes, but how do I proceed from there to get the filename of the image loaded into the imagePlane? Here's a portion of my code for the sceneLoaded callback:
void MayaExtractCalDataPlugin::sceneLoaded( void* clientData )
{
// Store the pointer to the current class
MayaExtractCalDataPlugin* crntPlugin = (MayaExtractCalDataPlugin*)clientData;
// We only enter the callback when isReadingFile() is false, as this indicates that all
// loading is complete. otherwise we would enter a whole series of callbacks when loading a scene
// with lots of references in.
if( !MFileIO::isReadingFile() )
{
// Traverse the scene and find image planes
// First we need to create an iterator to go through all image planes
MItDependencyNodes it(MFn::kImagePlane);
//iterate through all image planes
while(!it.isDone())
{
// Get the imagePlane object
MStatus status;
MObject object = it.thisNode(&status);
...
}
}
}
But, now that I have the MObject and I know its an imagePlane, I don't know how to get to the imageFile that is loaded into it. Thanks in advance for any help you can offer!

I figured it out! I just needed to add the following statements after the above code, and I can access all the imagePlane methods and attributes:
// attach a dependency node to the file node
MFnDependencyNode fn(object);
// get the attribute for the imageName path
MPlug imagePath = fn.findPlug("imageName");

Related

Load icon from .DLL in wxWidgets

I am attempting to load a wxIcon in Windows by loading from a system DLL (as the mime system told me that the icon for such a file type was in the DLL), eg.
wxIcon icon;
icon.LoadFile("C:\\WINDOWS\\system32\\zipfldr.dll", wxICON_DEFAULT_TYPE);
This fails but I was wondering if there was any way in the codebase of loading this, other than resorting to native Win32 functions.
Also, if there are native Win32 functions, does anyone know what they are?
EDIT: I have tried the following with no success:
::wxInitAllImageHandlers();
wxMimeTypesManager manager;
wxFileType* type = manager.GetFileTypeFromExtension("sys");
wxIconLocation location;
if (type->GetIcon(&location))
{
// location is something like C:\WINDOWS\system32\imageres.dll
wxIcon icon;
if (!icon.LoadFile(location.GetFileName(), wxBITMAP_TYPE_ICON /*I have tried wxICON_DEFAULT_TYPE too*/))
{
// Failed!
}
}
EDIT 2: In response to VZ, I have tried the following with no success sadly:
::wxInitAllImageHandlers();
wxMimeTypesManager manager;
wxFileType* type = manager.GetFileTypeFromExtension("sys");
wxIconLocation location;
if (type->GetIcon(&location))
{
// location is something like C:\WINDOWS\system32\imageres.dll,
//with an appropriate index as retrieved by location.GetIndex(), which is -67.
wxIcon icon(location);
if (!icon.IsOk())
{
BREAK;
// Failed!
}
}
EDIT 3:
Thanks for everyone's help - works fine if I use wxBITMAP_TYPE_ICO instead of wxBITMAP_TYPE_ICON (notice the N), and also I was putting my test code in my app's constructor instead of in ::OnInit. It worked in OnInit but not in the constructor so that's a lesson learned!
Thanks everyone for the help and speedy responses, much appreciated as always.
It should work if you specify type wxBITMAP_TYPE_ICO.
The first argument to LoadFile() must specify the icon resource ID when using wxBITMAP_TYPE_ICO (which is indeed what you need to use when loading icons from files, and not resources of the current module), i.e. you're also missing the ;N part at the end, where N is the value returned by wxFileTypeInfo::GetIconIndex().
But to avoid dealing with this explicitly, you should just use wxFileType::GetIcon() and construct wxIcon from the wxIconLocation filled in by it.
For example, this:
diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
index 0d91f7fc75..3623aacc56 100644
--- a/samples/minimal/minimal.cpp
+++ b/samples/minimal/minimal.cpp
## -123,6 +123,12 ## bool MyApp::OnInit()
if ( !wxApp::OnInit() )
return false;
+ wxIcon icon(wxIconLocation(R"(c:\Windows\system32\imageres.dll)", -67));
+ if ( icon.IsOk() )
+ {
+ wxLogMessage("Loaded icon of size %d*%d", icon.GetWidth(), icon.GetHeight());
+ }
+
// create the main application window
MyFrame *frame = new MyFrame("Minimal wxWidgets App");
shows the expected message about loading the icon of size 32 by 32.

How to load gif using wxWidgets c++?

I need your help! Im currently really new to wxWidgets as a uni student. I am trying to load a .gif file using wxWidgets. I tried using the code below... but it only loads 1 frame, it doesn't move/ change to the other frames, it's basically a still picture. The file is .gif extension, and it has 3 frames or so. The location of the image is already correct. Help would be much appreciated!
Thank you
#include "ImageWindow.h"
#include <wx/stdpaths.h>
#include <wx/filename.h>
BEGIN_EVENT_TABLE(ImageWindow, wxWindow)
EVT_PAINT(ImageWindow::OnPaint)
END_EVENT_TABLE()
ImageWindow::ImageWindow(wxFrame *parent)
: wxWindow(parent, wxID_ANY)
{
this->SetBackgroundColour(wxColour(*wxWHITE));
wxImageHandler *gifLoader = new wxGIFHandler();
wxImage::AddHandler(gifLoader);
this->LoadPotatoBitmap();
}
ImageWindow::~ImageWindow()
{
delete potatoBitmap;
}
void ImageWindow::LoadPotatoBitmap()
{
wxStandardPaths &stdPaths = wxStandardPaths::Get();
wxString fileLocation = stdPaths.GetExecutablePath();
wxImage image(wxT("A:\\Projects\\TestGif\\Assets\\Kuning.gif"),
wxBITMAP_TYPE_GIF);
potatoBitmap = new wxBitmap(image);
}
void ImageWindow::OnPaint(wxPaintEvent &event)
{
wxPaintDC pdc(this);
if (potatoBitmap != nullptr)
{
pdc.DrawBitmap(*potatoBitmap, wxPoint(150, 100), true);
}
}
You are not specifying the index of the image in the constructor and that's why you see the default one as you can see in the wxWdigets documentation:
wxImage::wxImage ( const wxString & name,
wxBitmapType type = wxBITMAP_TYPE_ANY,
int index = -1
)
index Index of the image to load in the case that the image file contains multiple images. This is only used by GIF, ICO and TIFF handlers. The default value (-1) means "choose the default image" and is interpreted as the first image (index=0) by the GIF and TIFF handler and as the largest and most colourful one by the ICO handler.
But, you should also consider wxAnimationCtrl (see this sample)
Use wxAnimationCtrl for playing gif animations
or
Use extract each frame from the gif image and draw one by one using wxTimer.

Osmdroid 5.6, offline MBTiles

I'm trying to use MBtiles offline with osmdroid,
I took code sample from here https://github.com/osmdroid/osmdroid/blob/master/OpenStreetMapViewer/src/main/java/org/osmdroid/samplefragments/tileproviders/SampleOfflineOnly.java
But always empty map shown, is there problem with my code?
my code is:
public class OSMDroid extends AppCompatActivity {
private MapView mapView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_osmdroid);
mapView = (MapView) findViewById(R.id.map);
String name = "map.mbtiles";
File f = new File(Environment.getExternalStorageDirectory() + "/osmdroid", name);
if (f.exists()) {
try {
//ok found a file we support and have a driver for the format, for this demo, we'll just use the first one
//create the offline tile provider, it will only do offline file archives
//again using the first file
OfflineTileProvider tileProvider = new OfflineTileProvider(new SimpleRegisterReceiver(this),
new File[]{f});
//tell osmdroid to use that provider instead of the default rig which is (asserts, cache, files/archives, online
mapView.setTileProvider(tileProvider);
//this bit enables us to find out what tiles sources are available. note, that this action may take some time to run
//and should be ran asynchronously. we've put it inline for simplicity
String source = "";
IArchiveFile[] archives = tileProvider.getArchives();
if (archives.length > 0) {
//cheating a bit here, get the first archive file and ask for the tile sources names it contains
Set<String> tileSources = archives[0].getTileSources();
//presumably, this would be a great place to tell your users which tiles sources are available
if (!tileSources.isEmpty()) {
//ok good, we found at least one tile source, create a basic file based tile source using that name
//and set it. If we don't set it, osmdroid will attempt to use the default source, which is "MAPNIK",
//which probably won't match your offline tile source, unless it's MAPNIK
source = tileSources.iterator().next();
mapView.setTileSource(FileBasedTileSource.getSource(source));
} else {
mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
}
} else {
mapView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
}
mapView.setUseDataConnection(false);
mapView.setBuiltInZoomControls(true);
IMapController mapController = mapView.getController();
mapController.setZoom(10);
GeoPoint startPt = new GeoPoint(61.5797,51.5997);
mapController.setCenter(startPt);
mapView.invalidate();
return;
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
MBTilesFileArchive getTileSources always returns empty string, here is implementation:
public Set<String> getTileSources(){
//the MBTiles spec doesn't store source information in it, so we can't return anything
return Collections.EMPTY_SET;
}
In order to make a offline map you should add tiles first. You can use Maperitive app to make your map tiles(zip is easier to manage than sql). Name the zip MapquestOSM. After you have done it create a folder "osmdroid" in phones memory(Directly into the internal memory or sd card) and add your map tiles in it.
Parameters of the XYTileSource changes related to the map tiles you have created. This code handles everything about map tiles itself. I hope it helps you
mapView.setUseDataConnection(false);
mapView.setTileSource(new XYTileSource("MapquestOSM", 2, 15, 256, ".png", new String[]{}));

captureScreen in cocos-2d C++ - how to use or save the captured image?

I want to have a button in my (iOS) app that takes a screenshot of the current screen and then attaches it to a text message.
Like I have seen in this other app...
I have message sending working, and I think I have screenshot working, but I don't know where the screenshot is saved or how to use it.
My message sending is called from a button in the app...
void GameOverScene::messageCallBack(cocos2d::Ref *sender) {
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(ALL_BUTTONS_CLICK_SOUND_NAME);
utils::captureScreen( CC_CALLBACK_2(GameOverScene::afterCaptured, this), "screenshot.png" );
__String *messageTextOne = __String::create("sms:&body=Hey,%20I%20just%20hit%20a%20score%20of%20");
__String *messageTextTwo = __String::createWithFormat("%i", score);
__String *messageURL = __String::createWithFormat("%s%s", messageTextOne->getCString(), messageTextTwo->getCString());
Application::getInstance()->openURL(messageURL->getCString());
}
and the screenshot function is...
void GameOverScene::afterCaptured( bool succeed, const std::string &outputFile ) {
if (succeed) {
log("Screen capture succeeded");
Size screenSize = Director::getInstance()->getWinSize();
RenderTexture * tex = RenderTexture::create(screenSize.width, screenSize.height);
tex->setPosition(screenSize.width/2, screenSize.height/2);
tex->begin();
this->getParent()->visit();
tex->end();
tex->saveToFile("Image_Save.png", Image::Format::PNG);
} else {
log("Screen capture failed");
}
}
I get the message in the console "Screen capture succeeded", and my message app opens up with the prefilled text message.
What I need to do is to add the screenshot to this message, but I cant see how to do that, or where the screenshot is saved, or how to use the saved screenshot.
If it succeeded it's saved in private application directory. Use software like iExplorer, find your app and it should be inside Documents directory. If you want to see it in Photos you have manually add it there.
In order to achieve this, you have to call
UIImageWriteToSavedPhotosAlbum
see: How to save picture to iPhone photo library?
You have to create a function in AppController.m and use it from here. You can call objc code from c++. It requires UIImage so first you have to pass filepath and load uiimage from it and then finally add to gallery.
You can use something like this to get the path of image saved:
void CustomLayerColor::saveFile(Node*node, std::string fileName, const renderTextureCallback& callBack) {
float renderTextureWidth = node->getBoundingBox().size.width;
float renderTextureHeight = node->getBoundingBox().size.height;
RenderTexture * renderTexture = RenderTexture::create(renderTextureWidth,renderTextureHeight);
renderTexture->begin();
node->visit();
renderTexture->end();
renderTexture->saveToFile(fileName, Image::Format::PNG, true,callBack);
}
void CustomLayerColor::onSaveFileCallBack(RenderTexture * mRenderTexture, const std::string& savedFileNameWithFullPath) {
}

How do I make a custom event with VTK?

I'm making a thread software with VTK, where I need to change the model itself in real time, while I need to change his method of rendering. Everything is working fine, but, the problem start with the interactor->start(); , the model data gets updated just fine, but it's only showed on screen when I move The camera. Also I have selected some methods for generating a 3D data from a imagedata file, for that I need to close the vtk window (interactor window) and then the code will reopen it and send the new data generated to it...
I would need something like these:
int force close_window = false; int refresh_interactor = false;
I managed to make the Window close, but only with vtkcommand::Keypressed command, but idk how do I do with a new command :S, I tried the vtkcommand::UserEvent but I didn't found a good information about how to deal with that data (like some way to call it)
the way I'm dealing with VTK is with two threads, the first one, is just about the vtk iren loop, and the second one would manage the models and check if iren requires to be updated.
In my dream code it should be something like this:
=======================================================
bool VTKWindow()
{
...
vtkSmartPointer ator = vtkSmartPointer::New();
iren = vtkSmartPointer::New();
RenWindow = vtkSmartPointer::New();
render->SetBackground(.1, .2, .3);
RenWindow->AddRenderer(renderer);
iren->SetRenderWindow(RenWindow);
if(data_type == voxel_type)
{
Render->AddViewProp(VoxelData);
}
else
{
actor->SetMapper(PolyData);
Render->AddActor(Actor);
}
RenWindow->Render();
iren->Start();
}
void ManageVTK()
{
while true loop...
if(force close_window == true)
do some command to exit the iren loop
if(refresh_interactor == true)
do some command to refresh iren
}
Sorry for the english, it's not my native language, and also sorry about the question format, it's the first time I'm using stackoverflow
It may sounds stupid, but, I found a kind of solution for the problem.
I saw on related links this guy vtkRenderWindowInteractor event loop and threading and, it's almost the same problem...
class VTKNewEvent : public vtkCommand{
public:
vtkTypeMacro(VTKNewEvent , vtkCommand);
static VTKNewEvent * New(){
return new VTKNewEvent ;
}
void Execute(vtkObject * caller, unsigned long vtkNotUsed(eventId), void * vtkNotUsed(callData)){
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor*>(caller);
if (iren_close == true){
iren->GetRenderWindow()->Finalize // Stop the interactor
iren->TerminateApp();
iren_close = false;
}
if (iren_update== true){
renderJanela->Render();
iren_update= false;
}
}
};
bool VTKWindow(){
vtkSmartPointer<VTKNewEvent > IrenRefresh= vtkSmartPointer<VTKNewEvent>::New();
...
iren->CreateRepeatingTimer(1);//this makes that IrenRefresh will be called at every 1ms
iren->AddObserver(vtkCommand::TimerEvent, IrenRefresh);
iren->Start();
...
}
it's simple, but, maybe not the best, but it did Th job, I hope this link will help people that are starting into the VTK world, since threads + rendering loop wasn't a simple job to understand what was going on