Могу ли я изменить цвет Emition на объект GLHudSprite в GLScene?

Я использую эту функцию, чтобы получить материал

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;

во-вторых, я добавляю процедуру перемещения мышей

Первые константные векторные цвета

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

создать объект

 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;

а затем процедура

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;

а вот функция ismouseoverImage...

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;

Теперь, когда указатель мыши находится над изображением, материал меняет цвет выброса, но я не получаю результатов... (я ничего не вижу).

Что я делаю не так...?

Спасибо...

4 ответа

Решение

Я собрал образец, демонстрирующий то, что я пытался объяснить. Единственная процедура, которая в нем содержится, назначает другой материал HUDSprite при наведении мыши и отменяет его выделение при наведении мыши.

    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;

Это все, что вам нужно, я прилагаю образец, включая все файлы. Пожалуйста, скачайте файлы проекта здесь: TestHUDSprite

Возможно, вам придется вызвать GlSceneViewer.Invalidate для обновления отображения. Кроме того, попробуйте не использовать режим текстурной модуляции и проверьте, работает ли он тогда, поскольку при использовании модуляции некоторые цветовые комбинации могут давать один и тот же результат, в зависимости от используемого фона и цветов излучения. Надеюсь это поможет.

Из того, что я вижу, вы добавляете материал в библиотеку материалов в своем первом фрагменте кода. Однако функция наведения мыши на изображение использует внутренний материал вашего HUD, а не тот, который вы определили в библиотеке. Если каждый HUDSprite имеет свою собственную текстуру и вы сохраняете все в MatLib, вам следует изменить свойства материала из MaterialLibrary, а не свойства внутреннего материала (каждый GLSceneObject поставляется с "внутренним" материалом, но вы можете назначить его материал библиотеки путем установки свойств MaterialLibrary и LibMatName.

//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)

а затем просто измените материал, как вы хотите.

Хорошо, так что это решение, которое я рекомендую, но оно зависит от того, насколько разные ваши материалы для каждого спрайта: когда вы создаете спрайты, не назначайте материал matlib каждому, просто скопируйте нужные свойства из материала matlib во внутренний материал каждого спрайта (как вы сделали выше). Таким образом, к каждому спрайту не нужно прикреплять какую-либо матрицу, а полагаться исключительно на его внутренний материал (вы просто используете материалы матрицы в качестве предварительных настроек), а затем, когда вы изменяете спрайты, вы просто изменяете, например, их внутренний цвет излучения. Недостатком этого подхода является то, что если у вас есть большое количество спрайтов, вместо совместного использования одной текстуры для всех, вы копируете эту конкретную текстуру для каждого спрайта, что неэффективно для памяти.

Другое решение, которое я также предлагаю, заключается в следующем: определите две версии для каждого материала в qyour matlib. Невыбранный и выбранный (у вас фактически будет два отдельных материала), и когда вам нужно выделить один спрайт, просто назначьте ему "выбранный материал" из matlib и назначьте "невыбранный материал" другим спрайтам.

В обоих случаях вам может понадобиться позвонить в Hudsprite.structurechanged, хотя я уверен, что в этом нет необходимости. Если подумать, если это так, я думаю, что второе решение - это то, которое я бы реализовал, потому что оно эффективно использует память, и вы можете иметь два совершенно разных вида для выбранных / невыбранных состояний.

Я надеюсь, что достаточно ясно, что я пытаюсь предложить здесь.

Другие вопросы по тегам