Question

i use this function to get the material

function AddMaterial(aMatLib: TGlMaterialLibrary; aFileName, aMaterialName: string):TGlLibMaterial;
begin
  result := aMatLib.Materials.Add;
  with result do
  begin
    with Material do
     begin
       MaterialOptions := [moIgnoreFog, moNoLighting];
       Texture.Disabled := false;
       BlendingMode := bmTransparency;
       Texture.TextureMode := tmModulate;
       with FrontProperties do
        begin
          Ambient.SetColor(1, 1, 1, 1);
          Diffuse.SetColor(1, 1, 1, 1);
          Emission.SetColor(1, 1, 1, 1);
          Specular.SetColor(1, 1, 1, 1);
        end;
      Texture.ImageClassName := 'TGLCompositeImage';
      if ExtractFileExt(aFileName) = '' then
        TGLCompositeImage(Texture.Image).LoadFromFile(aFileName + '.png')
      else
        TGLCompositeImage(Texture.Image).LoadFromFile(aFileName);
      //TGLCompositeImage(Texture.Image).LoadFromFile(aFileName);
   end;
    Name := aMaterialName;
  end;
end;

second i add an onmouse move procedure

first the const vector colors

const
  OnMoveInObjects_Color: TColorVector = (0.243, 0.243, 0.243, 1.000);
  OnOutObjects_Color: TColorVector = (0.000, 0.000, 0.000, 1.000);

create the object

 fsExit:= TGLHUDSprite.CreateAsChild(MainForm.Dummy_mainmenu);
 fsExit.Material.MaterialLibrary:= MatLib;
 fsExit.Material.LibMaterialName:= 'bexit';
 fsExit.SetSquareSize(50);
 fsExit.Position.X:= CenterX;
 fsExit.Position.Y:= 30;
 fsExit.Visible:= true;

and then the procedure

procedure Check_Mouse_UpPlayer(x,y:Integer);
 var
  sTVol: FLOAT;
begin
 if MainForm.IsMouseOverImage(fsExit,x,y) then
   begin
     fsExit.Material.FrontProperties.Emission.Color:= OnMoveInObjects_Color;
     if IsKeyDown(VK_LBUTTON) then
       begin
        fade_blur:= true;
        ShowExit;
      end;
    end
  else
   fsExit.Material.FrontProperties.Emission.Color:= OnOutObjects_Color;
end;

and here is the ismouseoverImage function...

function TMainForm.IsMouseOverImage(const AButton: TGLHudSprite; const X, Y: Integer):Boolean;
begin
  Result := (X >= AButton.Position.X - AButton.Width / 2) and (X <= AButton.Position.X + AButton.Width / 2) and
        (Y >= AButton.Position.Y - AButton.Height / 2) and (Y <= AButton.Position.Y + AButton.Height / 2);
end;

Now when the mouse is over the image the material change the emition color but i dont get results... (i don't see anything).

What i am doing wrong...?

Thank you...

Was it helpful?

Solution

I put together a sample showcasing what I tried to explain. The only procedure it contains assigns a different material to a HUDSprite on mouse over and deselects it on mouse out.

    procedure TForm1.GLSceneViewer1MouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
   if (X >= GLHUDSprite1.Position.X - GLHUDSprite1.Width * 0.5) and (X <= GLHUDSprite1.Position.X + GLHUDSprite1.Width * 0.5) and (Y >= GLHUDSprite1.Position.Y - GLHUDSprite1.Height * 0.5) and (Y <= GLHUDSprite1.Position.Y + GLHUDSprite1.Height * 0.5) then
   begin
      GLHUDSprite1.Material.LibMaterialName := 'Selected';
   end
   else
      GLHUDSprite1.Material.LibMaterialName := 'Unselected';
  GLSceneViewer1.Invalidate;
end;

This is all you need, I'm attaching the sample including all the files. Please download the project files from here: TestHUDSprite

OTHER TIPS

You might need to call a GlSceneViewer.Invalidate to update the display. Also, try not using texture modulation mode and check if it works then, since when using modulation, some color combinations can produce the same result, depending on the background and emission colors you use. Hope this helps.

from what I see you are adding a material to the material library in your first code snippet. However, your mouse over image function uses the internal material of your HUD, and not the one you defined in the library. If each HUDSprite has its own different texture and you store all in the MatLib, then you should modify the properties of the material from the MaterialLibrary and not those of the internal material (each GLSceneObject comes with an "Internal" material but you can assign it a library material by setting MaterialLibrary and LibMatName properties.

//This assumes that for each HUDsprite in your scene you have assigned a MateriaLibrary and LibMaterialName     
//you can get the library material assigned to a sprite like this:
    GLMaterialLibrary1.Materials.GetLibMaterialByName(CurrentHUDSprite.Material.LibMaterialName)

and then just alter the material any way you want.

ok, so this is the solution i recommend, but it depends on how different your materials are for each sprite: when you create the sprites, don't assign a matlib material to each one, just copy the properties you need from the matlib material into each sprite's internal material (as you did above). So each sprite should not have any matlib attached, but rely solely on its internal material (you just use the matlib materials as presets) and then when you alter sprites you simply modify thier inner emission color for example. the downside to this approach is that if you have a large number of sprites, instead of sharing one texture for all, you copy that particular texture for each sprite, which is not memory efficient.

Another solution I also suggest is the following: define two versions for each material in qyour matlib. A unselected one and a selected one (you will actually have two separate materials) and when you need to highlight one sprite just assign it the "selected material" from the matlib and assign the "unselected material" to the other sprites.

In both cases you might need to call Hudsprite.structurechanged although i'm pretty sure it's not required. Come to think if it, I think the second solution is the one I would implement cause it's memory efficient and you can have two completely different looks for selected/unselected states.

I hope it's clear enough what I'm trying to suggest here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top