Weird behavior of new figures in MATLAB - oop

I have created a class-managed GUI in which the following methods are defined
function h = make_figure(this)
h = figure('CloseRequestFcn',#this.close_figure);
this.openFigures(end+1) = h;
end
function close_figure(this, src, event)
this.openFigures(this.openFigures == src) = [];
delete(src);
end
Throughout the life of the GUI maney figures are created and closed with the aid of the methods above. Now the weird part...
If I double click a figure file eg (myfigure.fig) in MATLAB's "Current Folder" window and then try to close it (while the GUI is still alive) then the close_figure method of the GUI's class runs although it wasn't created with h = figure('CloseRequestFcn',#this.close_figure); of make_figure method!!! This is the first weird part. The second weird part is that, although an unintented part of code is executed, it shouldn't create problems because the command this.openFigures(this.openFigures == src) = []; actually leaves this.openFigures unchanged and practically all that close_figure does is to delete(src) which is desirable. Despite the above, my program behaves... weird after the above happens.
I have noticed that if I hit figure in the command window and then close it, everything is OK, the close_figure method is not executed. The problem reveals itself only when opening a .fig file created by the GUI's class.
Any ideas?

I just tried the scenario you described, and I am not seeing any weird behavior; create instance of the class, use it to make a figure, then open a FIG file from the "Current Folder" file browser, and close it..
Here is the class definition I used:
classdef MyFigureClass < handle
properties
openFigures = [];
end
methods
function h = make_figure(obj)
h = figure('CloseRequestFcn',#(src,evt) close_figure(obj,src,evt));
obj.openFigures(end+1) = h;
end
function close_figure(obj, src, evt)
obj.openFigures(obj.openFigures == src) = [];
delete(src);
end
end
end
(Tested in R2012a on Windows XP 32-bit.)
EDIT
Ok I think I know what the problem is. Here are the step to reproduce. First add the following method to the class above:
function save_figure(obj, idx)
saveas(obj.openFigures(idx), sprintf('fig%02d.fig',idx))
end
Now using our class wrapper, lets create a figure, and save it to FIG file:
f = MyFigureClass();
f.make_figure()
f.save_figure(1) %# creates fig01.fig
Next clear your workspace clear all, and move the class definition file MyFigureClass.m to some other folder (something not on the path). Now try to load the saved figure hgload fig01.fig, and it will throw the error:
Warning: Cannot load an object of class 'MyFigureClass':
Its class cannot be found.
> In C:\Program Files\MATLAB\R2012a\toolbox\matlab\graphics\hgload.p>localLoadFile at 167
In C:\Program Files\MATLAB\R2012a\toolbox\matlab\graphics\hgload.p>hgload at 59
In openfig at 72
In open at 159
In uiopen at 196
You will have to issue the following command to forcefully close it:
close all force
EDIT2
One solution (as mentioned in the comments), is to reset the figure close callback function just before saving it. Here is how I modified the save_figure function above:
function save_figure(obj, idx)
%# backup callback function
fcn = get(obj.openFigures(idx),'CloseRequestFcn');
%# set default callback function
set(obj.openFigures(idx),'CloseRequestFcn','closereq')
%# save figure
saveas(obj.openFigures(idx), sprintf('fig%02d.fig',idx))
%# restore callback function
set(obj.openFigures(idx),'CloseRequestFcn',fcn)
end

I just wanted to point out that there is a related issue here that others may face. You should NOT open your GUI by double clicking the gui.fig file. This is not the desired behavior because your opening function will never be called. Should you have code in there as many of us do it will not execute, another side effect is that the handles variable will also not be set properly.
What you SHOULD do is either open it in GUIDE first then click run, or run the gui.m file directly. That will yield the desired results and the gui will function as intended.

Related

GMOD Lua: How can I pass variables between scripts?

Im new to Lua and the gmod gamemode creation, and I'm having a bit of trouble. I want to deactivate a HUD when the game starts. I have 2 files, one the init.lua file, where a function is called that the game starts (there I want to change the value of HUD.lua) and a HUD.lua file, where the HUD is drawn and it contains the variable I want to change.
I tried multiple approaches, like referencing the script like:
hud.gameBegan = true
, but that didn't worked, so I tried also this putting into my init.lua:
SetNWBool("gameBegan", true)
and then I put this into the HUD.lua:
gameBegan = GetNWBool("gameBegan")
Lastly I tried this:
hud = AddCSLuaFile("hud.lua")
hud:gameChanged(true)
Unfortunatly, neither of these approaches worked for me, can somebody help me?
I would suggest keeping a table on the GM table for your gamemode to hold game states. This would then be synced between the server and the client using network messages.
Essentially how it will work is once the game starts, the server will send a network message to every player telling them that game started is true. When a new player joins, they will also need to know whether the game has started yet or not, and so we will also have to send a network message from the server to any new player that joins, telling them whether game started is true or false.
Once the game ends we need to also inform every player that the game has ended.
To start we need to store the states somewhere, and since whether a game has started or not relates to the gamemode it may be best to store it on the GAMEMODE table, and it also needs to be defined for the server and each player, so we should use the GAMEMODE table in gamemode/shared.lua:
GAMEMODE.States = GAMEMODE.States or {}
GAMEMODE.States.GameStarted = false
In your gamemode/init.lua file (which runs on the server) you may then add something like this:
util.AddNetworkString("MyGamemode.GameStartedSync")
function GM:SetGameStarted(hasStarted)
GAMEMODE.States.GameStarted = hasStarted
-- We have updated the state on the server, now update it
-- for each player on their client
net.Start("MyGamemode.GameStartedSync")
net.WriteBool(hasStarted)
net.Broadcast()
end
function GM:PlayerInitialSpawn(ply, transition)
BaseClass.PlayerInitialSpawn(self, ply, transition)
-- Player has joined, so send them the current game state
net.Start("MyGamemode.GameStartedSync")
net.WriteBool(GAMEMODE.States.GameStarted)
net.Send(ply)
end
If you already have a GM:PlayerInitialSpawn(ply) function then simply merge the contents of that one with yours.
(Note you will need DEFINE_BASECLASS("gamemode_base") at the top of your init.lua file to make BaseClass available if you don't already.)
In you gamemode/cl_init.lua file you need to now write the code on the player's client that can receive the network message:
net.Receive("MyGamemode.GameStartedSync", function()
local hasStarted = net.ReadBool()
GAMEMODE.States.GameStarted = hasStarted
end)
You can then set the sate of whether the game has started using GAMEMODE:SetGameStarted(true) or GAMEMODE:SetGameStarted(false) in any serverside script. And its value can be used with GAMEMODE.States.GameStarted on both the client and the server.
e.g.
if GAMEMODE.States.GameStarted then
DrawMyHud()
end
I am not familiar with GMod but maybe this can work?
In your init.lua file, you can use the include function to include the HUD.lua file and then set the variable to deactivate the HUD.
Here is an example:
include("HUD.lua") -- include the HUD file
HUDEnabled = false -- set the variable to false
In your HUD.lua file, you can then check the value of the variable before drawing the HUD:
if HUDEnabled then
-- code to draw HUD
end
You can also move the variable in the HUD.lua file so you can use it in the HUD.lua file and init.lua file.
-- HUD.lua
local HUDEnabled = true
if HUDEnabled then
-- code to draw HUD
end
-- init.lua
include("HUD.lua")
HUDEnabled = false

Godot: game gets stuck when trying to access local files

I have a function that gets an id, finds the relevant local text file, and returns the text from the file.
func load_file(book_id):
var file = placeholder_file % str(book_id)
var f = File.new()
f.open(file, File.READ)
var index = 1
while not f.eof_reached():
var line = f.get_line()
text_from_file += line
index += 1
f.close()
return(text_from_file)
This function seems to work fine when I run the game in Godot, but when exporting to HTML or Mac the game gets stuck at the exact moment when the function is triggered.
Found the source of the issue. Godot doesn't recognize .txt files and doesn't include them in the exported game unless explicitly instructed to do so.
To include .txt files in your exported game use the filter in the export window called: "filters to export non-resource files/folders"

Place Equipment From Ribbon Revit 2015: Transaction already started

Stack,
I'm programming an external application that works in Autodesk's Revit (2015). I've created a button on the ribbon that allows the user to place a special equipment that I'll use later to read and pass on to another process. I using 'TheBuildingCoder's' 'Family API' examples to do so. The button on the ribbon has an external command set in the .addin file in the ProgramData Directory...
<AddIn Type="Command">
<Assembly>C:\GSN Programs\MyDll.dll</Assembly>
<AddInId>{97715E4F-EA48-4690-8C62-B5D4836FF452}</AddInId>
<FullClassName>RcarsPlugIn.PlaceEquipment</FullClassName>
<VendorId>MyCompany, LLC</VendorId>
<Text>Place Equipment</Text>
<VisibilityMode>AlwaysVisible</VisibilityMode>
<Discipline>Any</Discipline>
<LanguageType>Unknown</LanguageType>
</AddIn>
On the button press, I put the command data into a global variable to use throughout the program...
If IsNothing(gv_oGo) Then
gv_oGo = New clsGeneralOperations
gv_oGo.CachedCommandData = exCommandData
gv_oGo.UiApp = exCommandData.Application.ActiveUIDocument.Application
End If
With the CommandData cached I move to place the equipment by user pick...
uiDoc = gv_oGo.UiApp.ActiveUIDocument
oSym = oRF.FindElement(doc, GetType(FamilySymbol), "MyEQUIP")
uiDoc.PromptForFamilyInstancePlacement(oSym)
Public Function FindElement(doc As Document, targetType As Type, sTargetName As String) As Element
Return New FilteredElementCollector(doc).OfClass(targetType).FirstOrDefault(Function(e) e.Name.Equals(sTargetName))
End Function
That's where the problem comes into play. I get an error message sent back from Revit stating that "Placement is not permitted in an already modifiable document. The active transaction must be closed first." The problem is, I haven't started a different transaction. The button onthe ribbon is the first that touched when Revit starts.
Is there a way to loop through the open transactions and find one that is open? Is the document in some state that I don't understand? I'm not sure which direction to turn here... any help would be appreciated.
Thanks,
Runnin...
Ok, one clarifying question - the exception is occurring on
uiDoc.PromptForFamilyInstancePlacement(oSym) line correct? if so, try using a subtransaction to complete your command instead:
Document doc = uiDoc.Document;
using (SubTransaction subtr_fam = new SubTransaction(doc))
{
try
{
uiDoc.PromptForFamilyInstancePlacement(oSym);
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace.ToString());
}
}

ObjectARX SDK for c#

For last two days I have looking for sample code with steps which may help me to understand the Autocad API. so I can use the code in C#.
[CommandMethod("LISTGEn")]
public static void ListEntities()
{
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,OpenMode.ForRead) as BlockTable;
// Open the Block table record Model space for read
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],OpenMode.ForRead) as BlockTableRecord;
int nCnt = 0;
acDoc.Editor.WriteMessage("\nModel space objects: ");
// Step through each object in Model space and
// display the type of object found
foreach (ObjectId acObjId in acBlkTblRec)
{
acDoc.Editor.WriteMessage("\n" + acObjId.ObjectClass.DxfName);
nCnt = nCnt + 1;
}
acDoc.Editor.WriteMessage(nCnt.ToString());
// If no objects are found then display a message
if (nCnt == 0)
{
acDoc.Editor.WriteMessage("\n No objects found");
}
// Dispose of the transaction
}
}
I can run the above code, but it's not functioning properly. It's difficult for me to understand how to get it work with Autocad. I have OjectARX SDK referenced,
I am working with VS2010 and Autocad 2012. Thank You for your help.
Ok, I got it only thing that is being required
1.) is to create a class library
2.) Then need to enter the above code in the class.
3.) Build your project by pressing F5.
4.) A DLL will be created in the bin/debug/ folder of your project
5.) Open Autocad.
6.) Write netload command.
7.) Select the DLL created and then write command "LISTGEN" and than kaboom it will show all the objects in your project.
To avoid having to manually netload your dll, you can use a temporary fix for debugging and write a lisp file to do it for you
(Command "netload" "path/to/your/.dll")\n
Or you can use \\
Take a look at my github. The link is on my profile. Look over the reference library, it's highly simplified for object model manipulation.
If you have any questions feel free to email me.

AHK: Manage multiple scripts

I got many scripts. I want to be able to manage them all in 1 in script.
What I want is that the main script will activate a certain script, then when the secondary script is done, it returns a value to the main script. After that, the main script calls another secondary script, etc...
Is there a proper way to do this?
More precise question:
Is it possible to activate a AHK script from another script AHK?
At the moment, to detect that at a secondary script is complete, the way I currently use is that right before the end of the secondary script, I press a combinaison of keys that the main script will detect. And once detected, it will increase a main script variable by one and this will trigger the activation of the next script. Is there a better way to achieve this?
The main script could call the other scripts using RunWait. The scripts could then communicate back before terminating themselves.
The best option for communication would be to use OnMessage.
The following is a working example from the documentation:
; Example: Send a string of any length from one script to another. This is a working example.
; To use it, save and run both of the following scripts then press Win+Space to show an
; InputBox that will prompt you to type in a string.
; Save the following script as "Receiver.ahk" then launch it:
#SingleInstance
OnMessage(0x4a, "Receive_WM_COPYDATA") ; 0x4a is WM_COPYDATA
return
Receive_WM_COPYDATA(wParam, lParam)
{
StringAddress := NumGet(lParam + 2*A_PtrSize) ; Retrieves the CopyDataStruct's lpData member.
CopyOfData := StrGet(StringAddress) ; Copy the string out of the structure.
; Show it with ToolTip vs. MsgBox so we can return in a timely fashion:
ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData%
return true ; Returning 1 (true) is the traditional way to acknowledge this message.
}
; Save the following script as "Sender.ahk" then launch it. After that, press the Win+Space hotkey.
TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey
#space:: ; Win+Space hotkey. Press it to show an InputBox for entry of a message string.
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel ; User pressed the Cancel button.
return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return
Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle) ; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.
{
VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0) ; Set up the structure's memory area.
; First set the structure's cbData member to the size of the string, including its zero terminator:
SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
NumPut(SizeInBytes, CopyDataStruct, A_PtrSize) ; OS requires that this be done.
NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize) ; Set lpData to point to the string itself.
Prev_DetectHiddenWindows := A_DetectHiddenWindows
Prev_TitleMatchMode := A_TitleMatchMode
DetectHiddenWindows On
SetTitleMatchMode 2
SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle% ; 0x4a is WM_COPYDATA. Must use Send not Post.
DetectHiddenWindows %Prev_DetectHiddenWindows% ; Restore original setting for the caller.
SetTitleMatchMode %Prev_TitleMatchMode% ; Same.
return ErrorLevel ; Return SendMessage's reply back to our caller.
}
Well, I'm not sure why you'd want to make one script run another one... but here are a few other methods:
Include a script in another one
but, you know you can include a script inside another one, right? That is, you can use another scripts functions in your main script.
Make sure a particular script is loaded
"I got many scripts" too. Sometimes I need to make sure that a particular one is included before I can use it, so I put this at the top:
;make sure core.ahk is loaded since it is required
#include c:\ahk\core.ahk
And you don't have to worry about it getting included more than once (unless you need it) because:
#Include ensures that FileName is included only once, even if multiple inclusions are encountered for it. By contrast, #IncludeAgain allows
multiple inclusions of the same file, while being the same as #Include
in all other respects.
Now, when I include file.ahk in main.ahk, I am assured of no problems using the functions from core.ahk that file.ahk requires. And even if I include core.ahk again in main.ahk it is no worry (unless it contains subroutines instead of just functions - in which case they get run at the point where they were included, so it's best not to put subroutines in your ahk libraries).
Use good ole' RUN on Scripts
Aside from that, you know you can always use the run command to launch an ahk script. You don't have to do all that fancy WM_SENDMESSAGE stuff.
Communicate betweenst scripts using a hidden GUI
Another way for two scripts to communicate between each other is for script #1 to keep open a hidden GUI window that has an edit box and a submit button. This window will never be shown. Now, Script #2 hunts for that message box, uses send to put a string in the edit box, and then control-click to push the submit button. Now script #1 has just received input from script #2. And you don't even have to hunt for the window if you put the windows hwnd value in both scripts (so they already know it ahead of time). This works like a charm.
Tell if a script has completed
If you use ahk's run command, there is an parameter that will give you back the PID of that process (PID = Process ID). You can use this PID to check to see if the script is running, and you can use it to terminate the process.
Also, if you use runwait - the script using that command will pause and wait for the runn-ed process to complete and close before continuing.
theoretically you could also use a file object between the scripts as a sort of stdin/stdout method as when opening a file with the file object you can set it as shared.
You could also set an environment variable and pass the name of the variable to the script ,given that you have setup argument handling in the target script, which then sets the environment variable value on closing. using RunWait and this you could find out what the return result of the script is after it runs.
Lastly, look into using a function as that is probably the "best practice" for what you are trying to do. Since a function can do anything a script can do and you can pass it an array to operate on or with using ByRef on the array param. This would mean that you don't have to write in a bunch of parameters when writing the function and the variables would release memory once the function is complete, automatically. You can even write your functions in a separate file and use #Include to use them in your script.