Compare a skulls display name to the name from the person who clicked it - compare

I'm trying to check if the players click on a player skull. Therefor Im using this method:
#EventHandler
public void onCLick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
if(event.getView().getTitle().equals("Inventory")) {
event.setCancelled(true);
if(!(event.getCurrentItem().getItemMeta().getDisplayName() == player.getDisplayName())) {
player.sendMessage("other player");
}else{
player.sendMessage("yourself");
}
}
But if I click on my own skull, I get the other “player output” and I dont know why…
This is how I create the skull item:
private ItemStack createSkull(Player player, String... lore) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) skull.getItemMeta();
meta.setDisplayName(player.getDisplayName());
meta.setOwningPlayer(player);
meta.setLore(Arrays.asList(lore));
skull.setItemMeta(meta);
return skull;
}

Not a complete answer but to optimize you code at line 6 replace: !(event.getCurrentItem().getItemMeta().getDisplayName() == player.getDisplayName()) by event.getCurrentItem().getItemMeta().getDisplayName() != player.getDisplayName()

Related

Unreal Engine 4: C++ Delegate not being called

I've been working on converting some blueprint logic over to C++. One of the things I have is a button. The button can be pressed in VR and has a delegate that is called to notify any registered functions that the button press occurred. Here is how the delegate is declared in the AButtonItem.h class.
#pragma once
#include "BaseItem.h"
#include "ButtonItem.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FButtonItemPressedSignatrue);
UCLASS()
class AButtonItem : public ABaseItem
{
GENERATED_BODY()
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Touch)
float myMaxButtonPress;
public:
UPROPERTY(EditAnywhere, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;
};
The delegate's broadcast function is then being called when the button is pressed like so:
ButtonItem_OnPressed.Broadcast();
(This function should defiantly be called because I have a debug statement that prints right before the call. Its also important to note this was all working when it was blueprint logic.)
Here is where I try to register with the delegate and how I declared the function that will be called:
WeaponMaker.h:
UFUNCTION()
void OnNextBladeButtonPressed();
WeaponMaker.cpp:
void AWeaponMaker::BeginPlay()
{
Super::BeginPlay();
TArray<USceneComponent*> weaponMakerComponents;
this->GetRootComponent()->GetChildrenComponents(true, weaponMakerComponents);
for (int componentIndex = 0; componentIndex < weaponMakerComponents.Num(); componentIndex++)
{
if (weaponMakerComponents[componentIndex]->GetName().Equals("NextBladeButton") == true)
{
myNextBladeButton = (AButtonItem*)weaponMakerComponents[componentIndex];
break;
}
}
if (myNextBladeButton != NULL)
{
myNextBladeButton->ButtonItem_OnPressed.AddDynamic(this, &AWeaponMaker::OnNextBladeButtonPressed);
}
}
I put a breakpoint and a print statement in the function OnNextBladeButtonPressed so I should immediately know when it works but its never happening. I also re-created the blueprint itself from scratch but still no luck. Sometimes on compile I get a crash due to the InvocationList being invalid but I haven't found much info on that issue either. Bottom line is, OnNextBladeButtonPressed is not getting called when it should be.
Edit: Here is where I call the broadcast function in my AButtonItem code. It seems to be getting called since i see the UE_LOG output in the console:
void AButtonItem::Tick(float deltaTime)
{
FTransform buttonWorldTransform;
FVector buttonLocalSpacePos;
FVector ownerLocalSpacePos;
FVector localDiff;
float buttonPressAmount;
if (myHasStarted == true)
{
Super::Tick(deltaTime);
if (myButtonComponent != NULL)
{
if (myPrimaryHand != NULL)
{
//Get the world space location of the button.
buttonWorldTransform = myButtonComponent->GetComponentTransform();
//Convert the location of the button and the location of the hand to local space.
buttonLocalSpacePos = buttonWorldTransform.InverseTransformPosition(myInitialOverlapPosition);
ownerLocalSpacePos = buttonWorldTransform.InverseTransformPosition(myPrimaryHand->GetControllerLocation() + (myPrimaryHand->GetControllerRotation().Vector() * myPrimaryHand->GetReachDistance()));
//Vector distance between button and hand in local space.
localDiff = ownerLocalSpacePos - buttonLocalSpacePos;
//Only interested in the z value difference.
buttonPressAmount = FMath::Clamp(FMath::Abs(localDiff.Z), 0.0f, myMaxButtonPress);
localDiff.Set(0.0f, 0.0f, buttonPressAmount);
//Set the new relative position of button based on the hand and the start button position.
myButtonComponent->SetRelativeLocation(myButtonInitialPosition - localDiff);
//UE_LOG(LogTemp, Error, TEXT("buttonPressAmount:%f"), buttonPressAmount);
if (buttonPressAmount >= myMaxButtonPress)
{
if (myHasBeenTouchedOnce == false)
{
//Fire button pressed delegate
if (ButtonItem_OnPressed.IsBound() == true)
{
ButtonItem_OnPressed.Broadcast();
AsyncTask(ENamedThreads::GameThread, [=]()
{
ButtonItem_OnPressed.Broadcast();
});
}
myHasBeenTouchedOnce = true;
myButtonComponent->SetScalarParameterValueOnMaterials("State", 1.0f);
Super::VibrateTouchingHands(EVibrationType::VE_TOUCH);
}
}
}
else
{
//Slowly reset the button position back to the initial position when not being touched.
FVector newPosition = FMath::VInterpTo(myButtonComponent->GetRelativeTransform().GetLocation(), myButtonInitialPosition, deltaTime, 10.0f);
myButtonComponent->SetRelativeLocation(newPosition);
}
}
}
}
First of all:
UPROPERTY(EditAnywhere, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;
This should be:
UPROPERTY(BlueprintAssignable, Category = Callback)
FButtonItemPressedSignatrue ButtonItem_OnPressed;
For convenience.
Secondly the tick function may be called before begin play is executed for a number of reasons. Your even't won't be broadcasted if the game hasn't begin play yet. So to avoid just add a check in your tick function.
if(bHasBegunPlay)
{
// .. your logics ...
}
Sometimes on compile I get a crash due to the InvocationList being invalid but I haven't found much info on that issue either. Bottom line is, OnNextBladeButtonPressed is not getting called when it should be.
I don't see any issue in the code from the question. At my glance, the issue could be in different location. I would suspect that AWeaponMaker had been deleted at moment of broadcasting.

Google Glass Mirror API - Is there a way to delete a bundle of cards?

I'm sending a bundle of cards to Glass with the Mirror API (c# library)
I know that you can use the default delete menu item on single cards, but is there a way to provide delete functionality for an entire bundle, ideally the result of one action by the users?
I have successfully used the DELETE action on a menu item with the code below
MenuItem mi = new MenuItem();
mi.Action = "DELETE";
TimelineItem tli = new TimelineItem()
{
Html = itemHtml.ToString(),
Notification = new NotificationConfig() { Level = "DEFAULT" },
MenuItems = new List<MenuItem>() { mi }
};
Is there a way to add this delete menu item to a bundle cover? I know this may be tricky because clicking the bundle cover causes you to navigate into the child cards thus no menu is present like on single cards. I'm looking for something (which I did try but it just ignored the menu item) like this:
MenuItem mi = new MenuItem();
mi.Action = "DELETE";
TimelineItem tli = new TimelineItem()
{
Html = itemHtml.ToString(),
Notification = new NotificationConfig() { Level = "DEFAULT" },
IsBundleCover = true,
BundleId = bundleId,
MenuItems = new List<MenuItem>() { mi }
};
If not possible on a cover card, is there a way to do this for a bundle by adding delete menu items to the child cards?
Any suggestions would be appreciated
You can use customized menu to do this. The code below is using Java but C# should be similar:
Add customized menu item to the card:
List<MenuValue> menuValueList = new ArrayList<MenuValue>();
menuValueList.add(new MenuValue().setIconUrl(iconUrl).setDisplayName("Delete All"));
MenuItem menuItem = new MenuItem();
menuItem.setValues(menuValueList).setId("delete_bundle_A").setAction("CUSTOM");
List<MenuItem> menuItemList = new ArrayList<MenuItem>();
menuItemList.add(menuItem);
timelineItem.setMenuItems(menuItemList);
Define the controller which handles the callback request of Mirror server notification:
if (notification.getCollection().equals("timeline") && notification.getUserActions().contains(new UserAction().setType("CUSTOM").setPayload("delete_bundle_A"))) {
deleteCards(credential, bundleId);
}
The delete card function:
// if bundleId is null or "", delete all cards
public static void deleteCards(Credential credential, String bundleId) throws IOException {
if (bundleId == null) {
bundleId = "";
}
Mirror.Timeline timelineItems = MirrorClient.getMirror(credential).timeline();
Mirror.Timeline.List list = timelineItems.list();
List<TimelineItem> timelineItemList = null;
do {
TimelineListResponse response = list.execute();
timelineItemList = response.getItems();
if (timelineItemList != null && timelineItemList.size() > 0) {
for (TimelineItem item : timelineItemList) {
if (bundleId == "" || bundleId.equalsIgnoreCase(item.getBundleId())) {
LOG.info("Deleting card " + item.getId());
MirrorClient.deleteTimelineItem(credential, item.getId());
}
}
list.setPageToken(response.getNextPageToken());
} else {
break;
}
} while (list.getPageToken() != null && list.getPageToken().length() > 0);
}
Finally, don't forget to subscribe timeline notification when application starts up:
String notifyUrl = "https://mirrornotifications.appspot.com/forward?url=" + "http://yourServer.com/notify";
Subscription subscription = MirrorClient.insertSubscription(credential, notifyUrl, userId, "timeline");
It isn't clear if you're asking how to create the menu items to delete the entire bundle at once, or if you're looking for code to do the actual delete.
Yuan provides some very good answers to both (not least of which because he actually provides code, which I won't), but there are three things you might also want to consider.
1) You can't have a menu on the bundle cover, but if you don't explicitly specify a bundle cover, then the most recent card will be shown as the cover and will also be shown as the first card in the bundle. You'd be able to get to the menu this way. (The default messaging app works this way, for example, but the first card has the same menu as the rest.)
2) You don't need to create a new menu item. You can leverage the DELETE menu item, if you wish. You'll get a delete notification for one of the cards in the bundle and you can then read the bundleId and delete the rest.
3) You don't need to loop through all the cards you've inserted just to find ones that have that bundleId. That is horribly inefficient. I am not fluent in C#, but from reading the documentation at https://developers.google.com/resources/api-libraries/documentation/mirror/v1/csharp/latest/classGoogle_1_1Apis_1_1Mirror_1_1v1_1_1TimelineResource_1_1ListRequest.html, I get the sense that you can create a ListRequest and then set the bundleId before executing the query and get the results.
So I think you can change Yuan's code to something like:
Mirror.Timeline.List list = timelineItems.list();
list.BundleId = bundleId;
List<TimelineItem> timelineItemList = null;
do {
TimelineListResponse response = list.execute();
timelineItemList = response.getItems();
if (timelineItemList != null && timelineItemList.size() > 0) {
for (TimelineItem item : timelineItemList) {
LOG.info("Deleting card " + item.getId());
MirrorClient.deleteTimelineItem(credential, item.getId());
}
list.setPageToken(response.getNextPageToken());
} else {
break;
}
} while (list.getPageToken() != null && list.getPageToken().length() > 0);
(this should be treated as pseudo-code, at best)
If you're confident how many items you've put into a bundle, you might also be able to just set list.MaxResults and not have to iterate over the pages of results. So perhaps something more like
Mirror.Timeline.List list = timelineItems.list();
list.BundleId = bundleId;
list.MaxResults = 20; // Set to more than the max number of items in a bundle
TimelineListResponse response = list.execute();
List<TimelineItem> timelineItemList = response.getItems();
if (timelineItemList != null && timelineItemList.size() > 0) {
for (TimelineItem item : timelineItemList) {
LOG.info("Deleting card " + item.getId());
MirrorClient.deleteTimelineItem(credential, item.getId());
}
}
There doesn't appear to be a way to delete a bundle in one step but it's still possible...
You can do a GET on /Timeline to get a list of items your app has pushed to the users timeline. Filter that out to find the entries with the bundleId you want to delete. For each of those items, call DELETE /Timeline/{itemid}

AddNewRecord XamDataGrid

After entering a value in the AddNewRecord row, and clicking anywhere outside the row on the XamDataGrid seems to add the row to the collection.
How do I prevent mouse click from adding a new row to the collection.
Kindly any help
Clicking outside of the AddNewRecord ends edit mode on the record and if there were changes they are committed at that time which means the new record is added. If you were looking to only allow the record to be commmited when pressing the enter key and not by clicking another record in the grid, then you could use the following logic to set the mouse left button down as handled:
private bool editingAddNewRecord = false;
void XamDataGrid1_EditModeEnded(object sender, Infragistics.Windows.DataPresenter.Events.EditModeEndedEventArgs e)
{
this.editingAddNewRecord = false;
}
void XamDataGrid1_EditModeStarted(object sender, Infragistics.Windows.DataPresenter.Events.EditModeStartedEventArgs e)
{
this.editingAddNewRecord = e.Cell.Record.IsAddRecord;
}
void XamDataGrid1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (editingAddNewRecord)
{
DataRecordPresenter drp = Infragistics.Windows.Utilities.GetAncestorFromType(e.OriginalSource as DependencyObject, typeof(DataRecordPresenter), true) as DataRecordPresenter;
if (!(drp != null && drp.IsAddRecord))
{
e.Handled = true;
}
}
}
Thanks for the answer #alhalama!
I noticed though that you don't handle the right mouse button down, and even when we do your solution doesn't work to support it. Also, with your solution I wasn't able to edit any other cells until I had hit Enter or Escape on the Add New Row record (which might be what some people want, but not me). Here is my modified solution that undoes changes to the Add New Record row's cell when the user clicks out of it, which also handles all mouse clicks (left, right, middle, etc.).
// Used to record when the user is editing a value in the Mass Edit row.
private DataRecord _addRecordCellBeingEdited = null;
private void XamDataGrid1_EditModeStarted(object sender, Infragistics.Windows.DataPresenter.Events.EditModeStartedEventArgs e)
{
if (e.Cell.Record.IsAddRecord)
_addRecordCellBeingEdited = e.Cell.Record;
}
private void XamDataGrid1_EditModeEnded(object sender, Infragistics.Windows.DataPresenter.Events.EditModeEndedEventArgs e)
{
_addRecordCellBeingEdited = null;
}
private void XamDataGrid1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (_addRecordCellBeingEdited != null)
{
DataRecordPresenter drp = Infragistics.Windows.Utilities.GetAncestorFromType(e.OriginalSource as DependencyObject, typeof(DataRecordPresenter), true) as DataRecordPresenter;
if (!(drp != null && drp.IsAddRecord))
{
_addRecordCellBeingEdited.CancelUpdate();
}
}
}

Why does this code not highlight the search term once found?

The code below does not highlight the search term when it is found. In fact the cursor disappears from the QPlainTextEdit (called ui->Editor) after pressing the 'next' button. What's causing it?
void TextEditor::findNextInstanceOfSearchTerm()
{
QString searchTerm = this->edtFind->text();
if(this->TextDocument == NULL)
{
this->TextDocument = ui->Editor->document();
}
QTextCursor documentCursor(this->TextDocument);
documentCursor = this->TextDocument->find(searchTerm,documentCursor);
if(!documentCursor.isNull())
{
documentCursor.select(QTextCursor::WordUnderCursor);
}else
{
ui->statusbar->showMessage("\""+searchTerm+"\" could not be found",MESSAGE_DURATION);
}
}
Firstly, your code creates a new cursor at the beginning of the document each time you press the next button, so you will always search from the beginning. Secondly, you must understand that the cursor you manipulate has nothing to do with the one in your QPlainTextEdit: you manipulate a copy. If you want to impact the text edit, you must modify its cursor using setTextCursor. Here is a working solution:
void TextEditor::findNextInstanceOfSearchTerm()
{
QString searchTerm = this->edtFind->text();
if(this->TextDocument == NULL)
{
this->TextDocument = ui->Editor->document();
}
// get the current cursor
QTextCursor documentCursor = ui->Editor->textCursor();
documentCursor = this->TextDocument->find(searchTerm,documentCursor);
if(!documentCursor.isNull())
{
// needed only if you want the entire word to be selected
documentCursor.select(QTextCursor::WordUnderCursor);
// modify the text edit cursor
ui->Editor->setTextCursor(documentCursor);
}
else
{
ui->statusbar->showMessage(
"\""+searchTerm+"\" could not be found",MESSAGE_DURATION);
}
}
As a side note, you might want to know that QPlainTextEdit provides a find method, so this might be an easier way to achieve what you want:
void TextEditor::findNextInstanceOfSearchTerm()
{
QString searchTerm = this->edtFind->text();
bool found = ui->Editor->find(searchTerm);
if (found)
{
QTextCursor cursor = ui->Editor->textCursor();
cursor.select(QTextCursor::WordUnderCursor);
ui->Editor->setTextCursor(cursor);
}
else
{
// set message in status bar
}
}
Use QTextCursor::EndOfWord
Use QPlainTextEdit::setExtraSelections to select/highlight something in QPlainTextEdit
Simply you already have cursor that would highlight word, but you didn't apply it to text edit

Adding Row Specific context menu to an UltraWinGrid

I'm a newbie using Infragistics. I'm trying to add context menu to a specific row/column in UltraWinGrid, which I'm not able to. Looks like adding context menu to the grid is simple but adding it to a specific row/column is not straight forward. Can you please tell me how to do this?
You could add a context menu to the form or control your grid will reside in and only display it in when they right click in the grid over the rows/cells that need that menu.
Here's an example, though it's not pretty.
private void UltraGrid_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
ContextMenu.Hide();
Point point = new System.Drawing.Point(e.X, e.Y);
UIElement uiElement = ((UltraGridBase) sender).DisplayLayout.UIElement.ElementFromPoint(point);
UltraGridCell cell = (UltraGridCell) uiElement.GetContext(typeof (UltraGridCell));
if (cell != null && UseThisContextMenu(cell))
{
ContextMenu.Show();
}
}
}
MouseDown does not work. Please use MouseUp.
private void UltraGrid1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Point point = new System.Drawing.Point(e.X, e.Y);
UIElement uiElement = ((UltraGridBase)sender).DisplayLayout.UIElement.ElementFromPoint(point);
UltraGridCell cell = (UltraGridCell)uiElement.GetContext(typeof(UltraGridCell));
if (cell.Band.Index == 0)
{
if (cell.Column.Key.Equals("ColumnToShow"))
{
contextMenuStrip.Show();
}
else
{
contextMenuStrip.Hide();
}
}
}
}
}